定义:

图是由由顶点的有穷非空集合和顶点之间边的集合组成,可以定义为:
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是图中边的集合

特点:

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

基本术语

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

邻接矩阵

#include 
#include 
#include 
#include 
#include 
#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;ivertexNumber;i++){
        for(int j=0;jvertexNumber;j++){
            printf("%d\t",g->edge[i][j]);
        }
        printf("\n");
    }
}
void Printf_All(GraphMatrix *g){
    int flag=1;
    for(int i=0;ivertexNumber;i++){
        if(flag){
            printf(" \t");
            flag=0;
        }
        printf("%c\t",g->vertex[i]);
    }
    printf("\n");
    for(int i=0;ivertexNumber;i++){
        printf("%c\t",g->vertex[i]);
        for(int j=0;jvertexNumber;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 (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;ivertexNumber;i++){
        g->edge[i]=(edgeType*)malloc(g->vertexNumber*sizeof(edgeType));
        for(int j=0;jvertexNumber;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 
#include 
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");
    }

你可能感兴趣的:(图)