一.邻接矩阵
图的邻接矩阵:用两个数组来表示图。一个一维数组存储图中的顶点信息,一个二维数组用来存储图中的边或弧的信息。
1. 主对角线全为0,因为不存在顶点到自身的值
2. 无向图的边数组是一个对称矩阵
3. 求顶点的度,如Vi的度,在邻接矩阵中第i行(第i列)的元素之和
4. 求顶点的邻接点,如vi的邻接点,扫描第i行,arc[i][j]为1就是邻接点
1. 主对角线全为0
2. 有向图的边数组矩阵不对称
3. 顶点Vi的入度,是第vi列的和,出度为vi行的和
1. 权来代替1
2. 无穷来代替0
代码实现
- #include<stdio.h>
- #include<string.h>
- #define MAXVEX 100
- #define INFINITY 65535
- typedef char VertexType;//顶点类型
- typedef int EdgeType;//边类型
- typedef struct{
- VertexType vexs[MAXVEX];//顶点数组
- EdgeType arc[MAXVEX][MAXVEX];//边数组
- int numVertexes,numEdges;//顶点数和边数
- }MGraph,*pMGraph;
- void createMGraph(pMGraph pMG){
- int i,j,k,w;
- puts("Enter the numVertexes and numEdges:");
- scanf("%d,%d",&(pMG->numVertexes),&(pMG->numEdges));//输入顶点数和边数
- puts("Enter the Vertexes:");
- for(i=0;i<pMG->numVertexes;i++){//依次输入顶点信息
- puts("Enter the vexs one by one:");
- scanf(&(pMG->vexs[i]));
- }
- for(i=0;i<pMG->numVertexes;i++){//初始化边数组为INFINITY
- for(j=0;j<pMG->numVertexes;j++){
- pMG->arc[i][j] = INFINITY;
- }
- }
- for(k=0;k<pMG->numEdges;k++){//依次输入边(vi,vj)的i、j和权值
- puts("Enter the edges");
- scanf("%d,%d,%d",&i,&j,&w);
- pMG->arc[i][j] = w;
- pMG->arc[i][j] = pMG->arc[j][i];//无向图是对称的,如果是有向图就省略这一步
- }
- }
二.邻接表
数组与链表相结合的方式称为邻接表。图中的顶点用一个一维数组存储,该数组中的数据元素有一个data域存储顶点信息,一个firstedge存储指向第一个邻接点的指针,所有邻接点以单链表存储,无向图称为vi的边表,有向图称为以vi的弧尾(出度)的出边表
1. 求某顶点的度,查找这个顶点的边表中的结点个数
2. 求某顶点的所有邻接点,则对边表进行遍历即可
1. 求某顶点的入度,查找这个顶点的出边表即可
2. 但是我们无法很快求出入度,所以可以建立一个逆邻接表
1. 对于带权图,我们可以在边表结点中添加一个weight的数据域存储权值即可
代码实现
- #include<stdio.h>
- #include<string.h>
- #include<stdlib.h>
- #define MAXVEX 100
- typedef char VertexType;
- typedef int EdgeType;
- typedef struct EdgeNode{//边表结点
- int adjvex;//邻接点域,存储该顶点对应的下标
- EdgeType weight;//权值
- struct EdgeNode *next;//链域,指向下一个邻接点
- }EdgeNode,*pEdgeNode;
- typedef struct VertexNode{//顶点表结点
- VertexType data;//顶点域,存储顶点信息
- pEdgeNode firstedge;//指向边表的头指针
- }VertextNode,*pVertextNode;
- typedef struct {//顶点表
- VertexNode adjList[MAXVEX];//顶点表数组
- int numVertexes,numEdges;//存储图中的顶点数和边数
- }GraphAdjList,*pGraphAdjList;
- void createALGraph(pGraphAdjList pGAL){
- int i,j,k;
- pEdgeNode e;
- puts("Enter the numVertexes and numEdges:");
- scanf("%d,%d",&(pGAL->numVertexes),&(pGAL->numEdges));
- for(i=0;i<pGAL->numVertexes;i++){//输入顶点表信息
- scanf(&(pGAL->adjList[i].data));//
- pGAL->adjList[i].firstedge = NULL;
- }
- for(k=0;k<pGAL->numEdges;k++){
- puts("Enter (Vi,Vj):");//输入边表信息
- scanf("%d,%d",&i,&j);
- e = (pEdgeNode)malloc(sizeof(EdgeNode));// 采用头插法
- e->adjvex = j;
- e->next = pGAL->adjList[i].firstedge;
- pGAL->adjList[i].firstedge = e;
- e = (pEdgeNode)malloc(sizeof(EdgeNode));//无向表,所以一条边对应两个顶点,要同时添加两个
- e->adjvex = i;
- e->next = pGAL->adjList[j].firstedge;
- pGAL->adjList[j].
三.十字链表(针对有向图)
将有向图的邻接表和逆邻接表结合起来
顶点表的结点结构变为
Data |
Firstin |
Firstout |
firstin表示入边表头指针,指向该结点的入边表中第一个结点
firstout表示出边表头指针,指向该结点的出边表第一个结点
边表结点的结构变为
Tailvex |
Headvex |
Headlink |
Taillink |
tailvex表示弧起点在顶点表中的下标
headvex表示弧终点在顶点表中的下标
headlink表示入边表指针域,指向终点相同的下一条边
taillink表示出边表指针域,指向起点相同的下一条边
1. 先完成出边表
2. 在完成入边表
3. 代码仍然使用头插法
四.邻接多重表(针对无向图)
边表结点结构为
Ivex |
Ilink |
Jvex |
Jlink |
ivex和jvex是依附于一条边的两个顶点在顶点表中的下标。ilink指向依附于ivex的下一条边。jlink执行依附于jvex的下一条边
五.边集数组
两个一维数组构成,一个存储顶点信息,另一个存储边的信息,这个边数组每个元素由起点下标、终点下标、权值组成。