邻接表非递归的深度优先遍历方法

描述:

无向连通图按邻接表存储结构存储的非深度优先遍历方法:

#include <iostream>
#include <cstdio>
#include <stack>
using namespace std;
typedef char VertexType; // 顶点类型
typedef int EdgeType; // 边上权值类型
typedef struct EdgeNode
{
	int adjvex; // 邻接点域,存储该顶点对应的下标
	EdgeType weight; // 用于存储权值,对于非网图可以不需要
	struct EdgeNode* next; // 链域
};
typedef struct VertexNode
{
	VertexType data; // 顶点域
	EdgeNode* firstEdge; // 边表头指针
}VertexNode, AdjList[100];
typedef struct
{
	AdjList adjList;
	int numVertexes, numEdges; // 图中当前顶点数和边数
}GraphAdjList;
void CreateALGraph(GraphAdjList& G)
{
	int i, j, k;
	EdgeNode* e;
	printf("输入顶点数和边数:\n");
	cin >> G.numVertexes >> G.numEdges;
	//printf("%d %d", G.numVertexes, G.numEdges);
	printf("输入顶点信息:\n");
	for (i = 0; i < G.numVertexes; ++i)
	{ // 输入顶点信息
		cin >> G.adjList[i].data;
		G.adjList[i].firstEdge = NULL; // 将边表置为空表
	}
	for (k = 0; k < G.numEdges; ++k)
	{
		printf("输入边(vi,vj)上的顶点序号:\n");
		cin >> i >> j;
		e = new EdgeNode;
		e->adjvex = j;
		e->next = G.adjList[i].firstEdge;
		G.adjList[i].firstEdge = e;

		e = new EdgeNode;
		e->adjvex = i; // 自己的邻接序号是i
		e->next = G.adjList[j].firstEdge;
		G.adjList[j].firstEdge = e;
	}
}
bool visited[100]; // 标记该顶点是否被访问过
void DFS(GraphAdjList G, int i)
{
	EdgeNode* p;
	visited[i] = true; // 该点被访问过
	printf("%c ", G.adjList[i].data);
	p = G.adjList[i].firstEdge;
	while (p)
	{
		if (!visited[p->adjvex])	DFS(G, p->adjvex);
		p = p->next;
	}
}
void DFSTraversal(GraphAdjList G)
{
	int i;
	for (i = 0; i < G.numVertexes; ++i)
	{
		visited[i] = 0;
	}
	for (i = 0; i < G.numVertexes; ++i)
	{
		if (!visited[i])	DFS(G, i);
	}
}

// 非递归DFS
void DFS2(GraphAdjList G, int i)
{
	stack<int> s;
	visited[i] = true; // 表示该点已经访问过
	cout << G.adjList[i].data << " ";
	s.push(i);
	while (!s.empty())
	{ // 栈不为空
		int tmp = s.top(); // 取栈顶元素
		EdgeNode* p = G.adjList[tmp].firstEdge;
		// 在序号为tmp顶点的边表中找未被访问过的顶点
		while (p && visited[p->adjvex])
		{
			p = p->next;
		}
		if (!p) s.pop(); // 没找到,则说明该顶点对应的边表遍历完了,弹出该顶点
		else {
			s.push(p->adjvex);
			cout << G.adjList[p->adjvex].data << " ";
			visited[p->adjvex] = true;
		}
	}
}
void DFSTraversal2(GraphAdjList G)
{
	int i;
	for (i = 0; i < G.numVertexes; ++i)
	{
		visited[i] = 0;
	}
	for (i = 0; i < G.numVertexes; ++i)
	{
		if (!visited[i]) DFS2(G, i);
	}
}
int main(void)
{
	GraphAdjList A;
	CreateALGraph(A);
	cout << "递归深度优先遍历结果:" << endl;
	DFSTraversal(A);
	cout << endl;
	cout << "非递归深度优先遍历结果:" << endl;
	DFSTraversal2(A);
	cout << endl;

	return 0;
}

测试结果

inform
result


讨论:

在上述代码中我将递归跟非递归方法都写了上去,目的是想作进一步对比。
从两种方法上看,不难发现,在遍历顶点边表的过程中,在递归方法中是不会重复遍历边表的,一个顶点的边表它遍历一次且仅只有一次。而在非递归方法中,它的边表是有可能重复遍历的,所以对于邻接表的非递归方法,如果不做进一步改进,它的时间复杂度是要高于递归方法的,也就是说在这种情况下我们最好还是用递归方法去实现深度优先遍历。
不过对于非递归方法可以通过进一步改进,比如说拿个数组来存遍历边表信息,可以解决这一问题,不过这样子就变复杂了,所以我还是比较推荐用递归去实现邻接表的深度优先遍历的。

  • 7
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小陌白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值