存储方式
邻接矩阵法
#define MaxVertexNum 100
typedef char VertexType;//顶点数据类型
typedef int EdgeType;//权值数据类型
typedef struct{
VertexType vertex[MaxVertexNum];
EdgeType edge[MaxVertexNum][MaxVertexNum];
int vertexNum,arcNum;//arc:弧
}MGraph;//由顶点(数组)、边(矩阵)、顶点数、边数构成的结构体
特点:
- 无向图的邻接矩阵一定是一个对称矩阵(压缩存储)
- 对于无向图,邻接矩阵的第i行(第i列)非零元素个数为第i个顶点的度TD(v_i)
- 对于有向图,邻接矩阵第i行非零元素个数为第i个顶点的出度OD(v_i),第i列非零元素个数为第i个顶点的入度ID(v_i)
- 要确定两点v_i与v_j是否相连,只要考察邻接矩阵
if(Edge[i][j] != 0){
}
时间复杂度为O(1)
要确定图中有多少条变,则需要
int num;
for(int i = 0;i < MaxVerTexNum;i++){
for(int j = 0;j < MaxVertexNum;j++){
if(Edge[i][j] > 0)num ++;
}
}
时间复杂度为O(n^2)
- 稠密图适合使用邻接矩阵的存储表示
- 设图G的邻接矩阵为A,A^n(i,j)等于由顶点i到顶点j的长度为n的路径的数目;
例如A^3(3,6)表示从第三个顶点到第六个顶点的长度为3的路径的数目;
邻接表法
arc. /ɑːk/ part of a circle or a curved line 弧
adjacent adj. /əˈdʒeɪsnt/ ~ (to sth) next to or near sth 与…毗连的;邻近的
顶点表:顶点域(data);边表头指针(firstarc)
边表:邻接点域(adjvex);指针域(nextarc)
顺序存储顶点的顶点信息和依附于该顶点(以该顶点为起点)的某一条边的指针构成的顶点表
链式存储依附于某个顶点的所有邻接点域(指向顶点表的指针/因为顶点是顺序存储的,可以用数组下标来表示邻接点域)和指针域(指向不与前序边重复的边的指针)构成的依附于该顶点(以该顶点为起点)的边的边表
#define MaxVertexNum 100
typedef struct ArcNode{ //结构体ArcNode存储边表
int adjvex; //该弧所指向的顶点的位置
struct ArcNode *next; //指向下一条弧的指针
//InfoType info; //网的边权值
}ArcNode;
typedef struct VNode{ //顶点表节点
VertexType data; //顶点信息
ArcNode *first; //指向第一条依附该顶点的弧的指针
}VNode,AdjList[MaxVertexNum];
typedef struct{
AdjList vertices; //邻接表
int vexnum,arcnum; //图的顶点数和弧数
}ALGraph; //ALGraph是以邻接表存储的图类型
特点:
- 若G为无向图,则需要的存储空间为O(|V|+2|E|);
- 若G为有向图,则需要的存储空间为O(|V|+|E|);
- 若G为稀疏图,则需要的存储空间将极大节省;
- 找出一个顶点地所有邻边快,时间复杂度为O(1)//表述不当;与之对比邻接矩阵为O(n);
- 判断给定两个顶点之间是否存在边较慢,时间复杂度依赖于节点关联的边数;与之对比邻接矩阵为O(1);
- 计算顶点v的出度只需要遍历v的边链表;计算入度要遍历整个邻接表
- 邻接表表示不唯一
十字链表
十字链表是有向图的一种结合了顺序存储和链式存储的存储结构,每一个顶点和每一条弧都有一个节点来存储,分别称之为顶点节点和弧节点。
顶点节点:data|firstin|firstout
- data:顶点信息
- firstout:以该顶点为弧头的第一个弧节点
- firstin:以该顶点为弧尾的第一个弧节点
弧节点:tailvex|headvex|hlink|tlink|info
- tailvex:尾域-指向弧尾顶点在图中的位置
- headvex:头域-指向弧头顶点在图中的位置
- hlink:指向弧头相同的下一条弧
- tlink:指向弧尾相同的下一条弧
- info:弧的相关信息(例如权值)
顶点节点之间顺序存储;弧节点之间链式存储。
邻接多重表
另一种类似于邻接表的链式存储结构
顶点节点:data|firstedge
- data:顶点信息
- firstedge:依赖于该顶点的第一条边的指针
弧节点:mark|ivex|ilink|jvex|jlink|info
- mark:访问标志
- ivex: 边依赖的第一个顶点节点的位置
- ilink:依赖于ivex顶点节点的下一条边的位置
- jvex:边依赖的第二个顶点节点的位置
- jlink:依赖于jvex顶点节点的下一条边的位置
- info:边的相关信息(权值等)
基本操作
- Adjacent(G,x,y):判断G中是否有边<x,y>或(x,y)
- Neighbors(G,x):列出图G中与节点x邻接的边
- InsertVertex(G,x):在图G中插入顶点x
- DeleteVertex(G,x):在图G中删除顶点x
- AddEdge(G,x,y):若无向边(x,y)或有向边<x,y>不存在,在图G中添加边(x,y)/<x,y>
- RemoveEdge(G,x,y):若无向边(x,y)或有向边<x,y>存在,在图G中移除边(x,y)/<x,y>
- FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号。若x不存在邻接点或G中不存在顶点x,则返回-1
- NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,返回-1
- GetEdgeValue(G,x,y):获取图G中边(x,y)/<x,y>的权值
- SetEdgeValue(G,x,y)::设置图G中边(x,y)/<x,y>的权值