前言
自己在学习图的DFS遍历时,对于书上的非递归形式的DFS过于简单,在写代码时难以下手。记录一下自己的思路。
步骤如下
1.创建有向/无向图
首先应当创建一个有向图/无向图,这个比较简单。对于无向图来说,将有向图的权值信息按对称矩阵复制一份即可。
//求顶点位置函数
int LocateVertex(AdjMatrix* G, VertexData v) {
int j, k;
for (k = 0; k < G->vexnum; k++) {
if (G->vertex[k] == v) {
j = k;
break;
}
}
return j;
}
//建立有向网图的邻接矩阵表示
void CreateAdjMatrix(AdjMatrix* G) {
int i, j, k, weight;
VertexData v1, v2;
printf("输入顶点数和边数\n");
scanf("%d,%d", &G->vexnum, &G->arcnum);
//对边表初始化
for (i = 0; i < G->vexnum; i++) {
for (j = 0; j < G->vexnum; j++) {
G->arcs[i][j].adj = INFNITY;
}
}
printf("输入顶点表\n");
for (i = 0; i < G->vexnum; i++) {
scanf(" %c", &G->vertex[i]);
}
printf("输入边表\n");
for (k = 0; k < G->arcnum; k++) {
scanf(" %c, %c,%d", &v1, &v2, &weight);
i = LocateVertex(G, v1);
j = LocateVertex(G, v2);
G->arcs[i][j].adj = weight;
//加上下面这行这就创建无向图。
G->arcs[j][i].adj = G->arcs[i][j].adj;
}
}
2.对于邻接矩阵的DFS遍历
接下是对于邻接矩阵的DFS遍历,递归遍历比较简单,这里就不写了。
重点是非递归遍历。
2.1邻接矩阵全节点的DFS遍历以及设置visited数组
无论是非递归遍历还是递归遍历,都会对顶点表创建一个visited数组,用来标志对该顶点是否访问过。所以对于DFS遍历来说,主要是对于v顶点的遍历不同,这里先列出对于整张图的设置visited数组和对全顶点的递归遍历。
int visited[MAX];
void NoReTraverseGraph(AdjMatrix g) {
//设置visited数组
for (int vi = 0; vi < g.vexnum; vi++) {
visited[vi] = 0;
}
//对全顶点遍历
for (int vi = 0; vi < g.vexnum; vi++) {
if (!visited[vi]) {
NoReDepthFirstSearch(g, vi);
}
}
}
2.2邻接矩阵vi节点的访问
接下是对单个节点的遍历访问,这里采用了stack容器来保存访问过的节点,对于最开始访问的节点vi,毫不犹豫进行入栈,再对vi的横向量的矩阵列进行判断。
这里vi最开始为0,那么设置w为0,即为横向量的纵坐标,想一想入栈的条件是什么,首先是w顶点没访问过,即visited[w]==0,并且和vi有连接,即g.arc[vi][w]==1,然后入栈,因为是深度优先,因此立刻停止搜索,按照w为顶点进行遍历。w则成为栈顶元素,因此在遍历横向量前应该先获取栈顶元素。
那么怎么出栈呢?那当然是w搜了一圈,没发现有连接的点或者都访问过了,简单点来说就是w>=边表的大小了,搜出去了都,当然要退栈了。
思路分析完毕,代码如下。
void NoReDepthFirstSearch(AdjMatrix g, int v) {
printf("%c ", g.vertex[v]);
//visit(v);
visited[v] = 1;
stack<int>S;
S.push(v);
while (!S.empty()) {
int top = S.top();
int w = 0;
for (w = 0; w < g.vexnum; w++) {
//如果没访问过并且还连着就访问入栈。
if (!visited[w] && g.arcs[top][w].adj == 1) {
printf("%c ", g.vertex[w]);
//visit(w);
visited[w] = 1;
S.push(w);
//立刻停止,对连着的这个元素进行遍历。(深度优先)
break;
}
}
//找了一圈都访问了或者都没连上,那就出栈。
if (w == g.vexnum) {
S.pop();
}
}
}
3.对于邻接表的DFS遍历
- 学会邻接矩阵,对邻接表照猫画虎也能写出来了。
- 代码如下
//邻接表非递归实现DFS
int visited[MAX];
void NoReDepthFirstSearch(AdjList g, int v0) {
//visit(v0);printf("%c",g.vertexlist[v0].data);
visited[v0] = 1;
stack<int>S;
S.push(v0);
while (!S.empty()) {
int top = S.top();
ArcNode* p = g.vertexlist[top].firstarc;
while (p != NULL) {
if (!visited[p->adjvex]) {
//visit(p->adjvex);printf("%c",g.vertexlist[p->adjvex].data);
visited[p->adjvex] = 1;
S.push(p->adjvex);
break;
}
}
if (p == NULL) {
S.pop();
}
}
}