01 基本概念
1、图的定义
图G(Graph)由顶点的有限集合V(G)和两个不同顶点的边的有限集合 E(G)构成,记为 G=(V,E)。
02 图的存储
2、图的存储结构
邻接矩阵
邻接表
图
a、邻接矩阵存储方法
邻接矩阵:顶点之间相邻关系的矩阵。
图G(V,E)含 n(n>0)个顶点,则G的邻接矩阵A是 n 阶方阵;其中顶点编号为
0 ~(n-1)。
共有四种类型
不带权无向图
不带权有向图
带权无向图
带权有向图
邻接矩阵定义
邻接矩阵
理解
E(G1)=
{(1,2),(1,3),(1,0),(2,3),(3,0),(2,4),(3,4),(4,0)}
它的邻接矩阵A1
图G1共5个顶点,即为5阶矩阵
无向边 (i,j)∈E(G) 共两条
存在一条边,则A[i][j]的值为1,否则为0
E(G3)=
{<0,1>,<0,3>,<1,2>,<2,4><3,2>}
它的邻接矩阵A3
图G3共5个顶点,即为5阶矩阵
有向边 ∈E(G)共一条
存在一条有向边,则A[i][j]的值为边的权重
邻接矩阵的特点
图的邻接矩阵表示是唯一的
存储空间固定 O(n2),适合存储稠密图
无向图的邻接矩阵一定是对称矩阵
无向图的邻接矩阵i行(或i列)非零元素(或非∞元素)的个数为顶点i的度
有向图的邻接矩阵i行(或i列)非零元素(或非∞元素)的个数为顶点i的出、入度
此方法容易确定两个顶点之间是否有边
数据类型定义
#define MAXV typedef struct{ int no;//顶点编号 InfoType info;//顶点其它信息}VertexType;//顶点类型typedef struct{ int edges[MAXV][MAXV];//邻接矩阵边数组 int n,e;//顶点数、边数 VertexType vexs[MAXV];//顶点信息}MGraph;//图的邻接矩阵类型
b、邻接表存储方法
邻接表:由顺序分配与链式分配结合。
图G(V,E)含 n(n>0)个顶点;每个顶点建立一个单链表,单链表中的节点代表依附于该顶点的边;每个单链表附设一个表头节点。
图G1的节点
图G1的邻接表构成
邻接表的特点
图的邻接表表示不唯一
邻接表适合存储稀疏图
无向图的邻接表的顶点对应的的边节点数为顶点的度
有向图的邻接表的顶点对应的的边节点数为顶点的出度
数据类型定义
typedef struct ANode{ int adjvex;//该边的终点编号 struct ANode * nextarc;//指向下一条边的指针 InfoType info;//该边的相关信息}ArcNode;//边节点类型typedef struct Vnode{ Vertex data;//顶点信息 ArcNode * firstarc;//指向第一条边}VNode;//邻接表头节点类型typedef VNode AdjList[MAXV];//邻接表类型typedef struct{ AdjList adjlist;//邻接表 int n,e;//顶点数、边数}ALGraph;//图的邻接表类型
03 图的遍历
3、图的遍历概念
从指定的顶点出发,沿着图的边访问图中所有节点,每个节点仅被访问一次。
分类
深度优先(DFS)
广度优先(BFS)
a、深度优先
从初始顶点出发,先访问初始顶点,再访问与初始顶点相邻且没被访问过的顶点;递归以上逻辑,直到每个节点都被访问。
邻接表实现DFS
void DFS(ALGraph *G, int v){ ArcNode *p; visited[v]=1; printf("%d",v); p=G->adjlist[v].firstarc; while(p!=NULL) { if(visited[p->adjvex]==0) DFS(G,p->adjvex); p=p->nextarc; }}
以图G1的邻接表顶点2进行深度优先遍历
访问序列为(2、1、0、3、4)
深度优先执行过程
b、广度优先
从初始顶点出发,按顺序访问所有与初始顶点相邻的顶点;再按初始顶点访问的顺序,依次访问每个顶点所有未被访问过的相邻顶点。
邻接表实现BFS
void BFS(ALGraph *G, int v){ ArcNode *p; int queue[MAXV], front=0, rear=0; int visited[MAXV]; int w,i; for(i=0;in;i++) visited[i]=0; printf("%2d",v); visited[v]=1; rear=(rear+1) % MAXV; queue[rear] = v; whiel(front!=rear) { front = (front+1)%MAXV; w=queue[front]; p=G->adjlist[w].firstarc; while(p!=NULL) { if(visited[p->adjvex]==0) { printf("%2d",p->adjvex); visited[p->adjvex]=1; rear=(rear+1)%MAXV; queue[rear]=p->adjvex; } p=p->nextarc; } } printf("\n");}
以图G1的邻接表顶点2进行广度优先遍历
访问序列为(2、1、3、4、0)
版权说明:
封面图片来自网络,侵删。
原创文章,只供学习交流。
参考《数据结构教程 第4版》