图的深度优先遍历
邻接矩阵遍历
分析邻接矩阵结构
根据上图我们知道,相连接的两个顶点的值为1,所以遍历图的时候需要判断两个顶点是否连接
使用一个数组来记录当前的顶点是否进行了遍历
代码实现逻辑
代码实现
#include <stdio.h> #include <stdlib.h> #include "math.h" #include "time.h" #define TRUE 1 #define FALSE 0 typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */ typedef char VertexType; /* 顶点类型应由用户定义 */ typedef int EdgeType; /* 边上的权值类型应由用户定义 */ #define MAXSIZE 9 /* 存储空间初始分配量 */ #define MAXVEX 9 typedef struct { VertexType vexs[MAXVEX]; /* 顶点表 */ EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */ int numVertexes, numEdges; /* 图中当前的顶点数和边数 */ }MGraph; /*4.1 构建一个邻接矩阵*/ void CreateMGraph(MGraph *G) { int i, j; //1. 确定图的顶点数以及边数 G->numEdges=15; G->numVertexes=9; /*2.读入顶点信息,建立顶点表 */ G->vexs[0]='A'; G->vexs[1]='B'; G->vexs[2]='C'; G->vexs[3]='D'; G->vexs[4]='E'; G->vexs[5]='F'; G->vexs[6]='G'; G->vexs[7]='H'; G->vexs[8]='I'; /*3. 初始化图中的边表*/ for (i = 0; i < G->numVertexes; i++) { for ( j = 0; j < G->numVertexes; j++) { G->arc[i][j]=0; } } /*4.将图中的连接信息输入到边表中*/ G->arc[0][1]=1; G->arc[0][5]=1; G->arc[1][2]=1; G->arc[1][8]=1; G->arc[1][6]=1; G->arc[2][3]=1; G->arc[2][8]=1; G->arc[3][4]=1; G->arc[3][7]=1; G->arc[3][6]=1; G->arc[3][8]=1; G->arc[4][5]=1; G->arc[4][7]=1; G->arc[5][6]=1; G->arc[6][7]=1; /*5.无向图是对称矩阵.构成对称*/ for(i = 0; i < G->numVertexes; i++) { for(j = i; j < G->numVertexes; j++) { G->arc[j][i] =G->arc[i][j]; } } } #pragma mark - 定义bool类型的数组用来记录该顶点是否被遍历 Boolean visit[MAXSIZE] = {FALSE}; //从index顶点开始遍历 void DFSVisit(MGraph map, int index){ //设置成遍历过了 visit[index] = TRUE; //打印当前遍历的顶点 printf("当前遍历的顶点是:%c\n",map.vexs[index]); for (int i = 0; i<map.numVertexes; i++) { //递归遍历 if (map.arc[index][i] == 1 && !visit[i]) { DFSVisit(map, i); } } } int main(int argc, const char * argv[]) { // insert code here... printf("Hello, World!\n"); MGraph map; CreateMGraph(&map); for (int i = 0; i<map.numVertexes; i++) { if (!visit[i]) { DFSVisit(map, i); } } return 0; }
邻接表的遍历
- 邻接表的结构
邻接表的代码实现逻辑思路
代码实现(核心代码)
#pragma mark - 定义bool类型的数组用来记录该顶点是否被遍历 Boolean visit[MAXSIZE] = {FALSE}; //从index顶点开始遍历 void DFSVisit(GraphAdjList map, int index){ //设置成遍历过了 visit[index] = TRUE; //打印当前遍历的顶点 printf("当前遍历的顶点是:%c\n",map->adjList[index].data); EdgeNode *temp = map->adjList[index].firstedge; while (temp) { if (!visit[temp->adjvex]) { DFSVisit(map, temp->adjvex); } temp = temp->next; } } int main(int argc, const char * argv[]) { // insert code here... printf("Hello, World!\n"); MGraph G; GraphAdjList GL; CreateMGraph(&G); CreateALGraph(G,&GL); for (int i = 0; i<GL->numVertexes; i++) { if (!visit[i]) { DFSVisit(GL, i); } } return 0; }
广度优先遍历
广度优先遍历的特点
- 把根节点放到队列的末尾
- 每次从队列的头部取出一个元素,查看这个元素下的所有的下一级元素,把它们放在队列的末尾,并把这个元素记为它下一级元素的前驱
- 找到所要找到的元素时结束程序
- 如果遍历整个树还没有找到则结束程序
广度优先遍历的图示结构
邻接矩阵遍历代码实现
Boolean visit[MAXSIZE] = {FALSE};
void BFSVisit(MGraph Map){
Queue Q;
InitQueue(&Q);
//遍历顶点
for (int i = 0; i<Map.numVertexes; i++) {
if (!visit[i]) {//当前顶点还没与遍历
visit[i] = TRUE;
//打印当前的顶点
printf("当前遍历的顶点是:%c\n",Map.vexs[i]);
//入栈
EnQueue(&Q, i);
while (!QueueEmpty(Q)) {
//出队
DeQueue(&Q, &i);
for (int j = 0; j < Map.numVertexes; j++) {
if(Map.arc[i][j] == 1 && !visit[j])
{ visit[j] = TRUE;
printf("当前遍历的顶点是:%c\n",Map.vexs[j]);
EnQueue(&Q, j);
}
}
}
}
}
}
int main(int argc, const char * argv[]) {
// insert code here...
printf("Hello, World!\n");
MGraph Map;
CreateMGraph(&Map);
BFSVisit(Map);
printf("\n");
return 0;
}
邻接表遍历代码实现
Boolean visit[MAXSIZE] = {FALSE};
void BFSVisit(GraphAdjList Map){
//创建结点
EdgeNode *p;
Queue Q;
InitQueue(&Q);
for (int i = 0; i<Map->numVertexes; i++) {
if (!visit[i]) {
visit[i] = TRUE;
EnQueue(&Q, i);
printf("当前遍历的顶点是:%c\n",Map->adjList[i].data);
while (!QueueEmpty(Q)) {
DeQueue(&Q, &i);
p = Map->adjList[i].firstedge;
while (p) {
if (!visit[p->adjvex]) {
visit[p->adjvex] = TRUE;
printf("当前遍历的顶点是:%c\n",Map->adjList[p->adjvex].data);
EnQueue(&Q, p->adjvex);
}
p = p->next;
}
}
}
}
}