2018-10-01  本文已影响0人  掖莯圷

定义:

图是由由顶点的有穷非空集合和顶点之间边的集合组成,可以定义为:
G=(V, E)
其中,
V = {x|x∈某个数据元素集合}
E ={(x,y)|x,y∈V} 或
E = {<x, y>|x,y∈V并且Path(x, y)}

其中,(x,y)表示从 x到 y的一条双向通路,即(x,y)是无方向的;Path(x,y)表示从 x到 y的一条单向通路,即Path(x,y)是有方向的。
简单来说:G是图,V是图中顶点的集合,E是图中边的集合

特点:

在线性表中,每个元素之间只有一个直接前驱和一个直接后继,
在树形结构中,数据结构是层次关系,并且每一层上的数据可能和下一层中多个元素相关,但只能和上一层中一个元素相关
非线性结构,是研究数据元素之间的多对多的关系。在这种结构中,任意两个元素之间可能存在关系。即结点之间的关系可以是任意的,图中任意元素之间都可能相关

基本术语

\color{red}{顶点:}在图中的数据元素,我们称之为顶点(Vertex)
\color{red}{边:}顶点之间的逻辑关系用边来表示,边集可以是空的
\color{red}{无向边:}若顶点{V_i到V_j}之间的边没有方向,则称这条边为无向边,用无序偶({V_i,V_j})来表示
\color{red}{无向图:}图中的每一条边都是没有方向的
\color{red}{有向边:}若顶点{V_i到V_j}之间的边有方向,则称这条边为有向边,也称为弧(Arc),用有序偶<{V_i,V_j}>来表示,{V_i}称为弧尾,{V_j}称为弧头
\color{red}{有向图:}图中的每一条边都是有方向的
\color{red}{简单图:}在图结构中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图
\color{red}{无向完全图:}在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。含有n个顶点的无向完全图有n(n-1)/2条边。
\color{red}{有向完全图:}在有向图中,如果任意两个顶点之间都存在互为相反的两条弧,则称该图为有向完全图。含有n个顶点的无向完全图有n
(n-1)条边。
\color{red}{稀疏图和稠密图:}通常认为边或弧数小鱼n*logn(n是顶点的个数)的图称为稀疏图,反之称为稠密图。
\color{red}{权:}有些边或弧带有与他相关的数字,这种与图的边或弧相关的数字,称为权
\color{red}{网:}带权的图称为网
\color{red}{子图:}假设有两个图,G1=(V1, E1) 和 G2=(V2, E2)。如果V2∈V1 且 E2∈E1,则称G2为G1的子图

邻接矩阵

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#define isLetter(a)  ((((a)>='a')&&((a)<='z')) || (((a)>='A')&&((a)<='Z')))
#define LENGTH(a)  (sizeof(a)/sizeof(a[0]))
typedef char vertexType;
typedef int edgeType;
typedef struct _GraphMatrix{
    int vertexNumber;// 顶点数
    int edgeNumber; // 边数
    vertexType *vertex;// 顶点集合
    edgeType **edge;// 邻接矩阵
}GraphMatrix;

void Printf_G(GraphMatrix *g){
    for(int i=0;i<g->vertexNumber;i++){
        for(int j=0;j<g->vertexNumber;j++){
            printf("%d\t",g->edge[i][j]);
        }
        printf("\n");
    }
}
void Printf_All(GraphMatrix *g){
    int flag=1;
    for(int i=0;i<g->vertexNumber;i++){
        if(flag){
            printf(" \t");
            flag=0;
        }
        printf("%c\t",g->vertex[i]);
    }
    printf("\n");
    for(int i=0;i<g->vertexNumber;i++){
        printf("%c\t",g->vertex[i]);
        for(int j=0;j<g->vertexNumber;j++){
            printf("%d\t",g->edge[i][j]);
        }
        printf("\n");
    }
}
/*
 * 返回ch在matrix矩阵中的位置
 */
int Get_Position(GraphMatrix g, char ch){
    int i;
    for(i=0; i<g.vertexNumber; i++){
        if(g.vertex[i]==ch)
            return i;
    }
    return -1;
}
/*
 * 读取一个输入字符
 */
char Read_Char(){
    char ch;
    do {
        ch = getchar();
    } while(!isLetter(ch));
    return ch;
}
void Init_GraphMatrix(GraphMatrix *g){
      //初始化图
    int v,e;
    printf("请输入顶点数量:");
    scanf("%d",&v);
    printf("请输入边数量:");
    scanf("%d",&e);
    if ( v < 1 || e < 1 || (e > (v * (v-1)))){
        printf("输入参数有误!\n");
        exit(0);
    }
    g->vertexNumber=v;
    g->edgeNumber=e;
    //分配空间
    g->vertex=(vertexType*)malloc(g->vertexNumber*sizeof(vertexType));
    // 初始化"边"
    g->edge=(edgeType**)malloc(g->vertexNumber*sizeof(edgeType));
    for(int i=0;i<g->vertexNumber;i++){
        g->edge[i]=(edgeType*)malloc(g->vertexNumber*sizeof(edgeType));
        for(int j=0;j<g->vertexNumber;j++){
            g->edge[i][j]=0;
        }
    }
    printf("初始化完毕\n");
    Printf_G(g);
}


GraphMatrix* Create_GraphMatrix(){
    char c1, c2;
    int p1, p2;
    GraphMatrix *g;
    if ((g=(GraphMatrix*)malloc(sizeof(GraphMatrix))) == NULL )
    return NULL;
    memset(g, 0, sizeof(GraphMatrix));
    Init_GraphMatrix(g);
    for (int i = 0; i < g->vertexNumber; i++){
        printf("请输入顶点(%d)的值: ", i);
        g->vertex[i] = Read_Char();
    }
    for (int i = 0; i < g->edgeNumber; i++){
        // 读取边的起始顶点和结束顶点
        printf("请输入边(%d)起始顶点和结束顶点:", i);
        c1 = Read_Char();
        c2 = Read_Char();
        p1=Get_Position(*g, c1);
        p2=Get_Position(*g, c2 );
        if (p1==-1 || p2==-1){
            printf("输入有误: 无效的边!\n");
            free(g);
            exit(0);
        }
        g->edge[p1][p2]=1;
        g->edge[p2][p1]=1;
    }
    Printf_All(g);
    return g;
}


int main()
{
    GraphMatrix *gm=Create_GraphMatrix();

    return 0;
}

邻接表

#include <stdio.h>
#include <stdlib.h>
typedef char vertexType;
typedef struct ListEdgeNode{
    int index;                  // 边的下标
    struct ListEdgeNode *next;          // 指向下一个节点的指针
}ListEdgeNode;

typedef struct ListVertexNode {
    vertexType vertex;          // 顶点
     ListEdgeNode *fistEdge;        // 指向第一条边
} ListVertexNode;

typedef struct GraphList{
    int vertexNumber;           // 顶点的数量
    int edgeNumber;             // 边的数量
    ListVertexNode *vertex;     // 顶点集合,动态数组
}GraphList;
void GraphList_create(GraphList *g){
    printf("请分别输入图的顶点数量和边的数量,用空格隔开:");
    scanf("%d %d", &g->vertexNumber, &g->edgeNumber);       //将顶点数量和边的数量存储在结构体g中相应的变量
    //为动态数组申请空间
    g->vertex = (ListVertexNode*)malloc(g->vertexNumber * sizeof(ListVertexNode));
    //初始化顶点指的第一条边
    for (int i = 0; i < g->edgeNumber; i++){
        g->vertex[i].fistEdge = NULL;
    }

    //输入图的信息
    ListEdgeNode *listEdgeNode;
    for (int k = 0; k < g->edgeNumber; k++){
        int i, j;
        printf("请输入边(vi,vj)的下标, i和j,用空格隔开:");
        scanf("%d%d", &i, &j);
        //始终将插入的节点放在顶点所指的地一条边
        listEdgeNode = (ListEdgeNode *)malloc(sizeof(ListEdgeNode));
        listEdgeNode->index = j;
        listEdgeNode->next = g->vertex[i].fistEdge;
        g->vertex[i].fistEdge = listEdgeNode;

        listEdgeNode = (ListEdgeNode*)malloc(sizeof(ListEdgeNode));
        listEdgeNode->index = i;
        listEdgeNode->next = g->vertex[j].fistEdge;
        g->vertex[j].fistEdge = listEdgeNode;

    }

    //输出图的信息
    ListEdgeNode * len = NULL;
    for (int i = 0; i < g->vertexNumber; i++){
        
        if (g->vertex[i].fistEdge != NULL)
            len = g->vertex[i].fistEdge;
        while (len!= NULL){
            printf("%d --- %d\t", i,len->index);
            len = len->next;
        }
        printf("\n");
    }
上一篇下一篇

猜你喜欢

热点阅读