图的深度优先遍历

思路:任选一点开始,在该点能到达的点中选一个去遍历(其余的点等稍后再说),在第二个点访问过之后,类似访问过第一个点之后,选其能到达的点中的一个去遍历,一直到某个点访问完,但他又没有其他相邻的点,此时,再回到他的上一个点,访问该点未访问过的临接点,若无,继续向上回溯。。。。

例:

(此图和该文的思路是参考  http://blog.csdn.net/todd911/article/details/9191481  后自己的总结)


(在选起始点和访问邻接点时我们的原则是从小到大)首先,访问0,接着是3,再接着是1。此时,1没有可以到达的邻接点,故返回3,3的两个邻接点1,2,1已经访问,故我们访问2。然后2又没有可以到达的邻接点,返回3,3虽然有两个可以到达的邻接点,但是都已经访问过了!故再返回1(仅仅是返回并不访问,上同),1的邻接点4未访问,到达4。4没有未访问的邻接点,返回0,0也没有,结束。故dfs访问到的顺序是:0,3,1,2,4

代码思路: dfs(0),找到邻接点3,dfs(3),dfs(1),1没有未访问的邻接点,返回。dfs(3),1访问过了,dfs(2),返回,dfs(3),返回。。。。首先,我们应有个向量来记录点是否已被访问,否则,例如我们访问到1,发现1没有未访问的邻接点,返回dfs(3)的时候,又要访问1,这显然是不行的。另外在dfs(3)的时候,也应区分是第一次还是第二次,若是第一次就要输出,否则,不输出。核心是dfs()函数。

c++代码:

#include <iostream>
#include <vector>
using namespace std;

#define VERTEXNUM 5

void CreateTable(vector<vector<int>>& table, int row, int column)
{
	table[row][column] = 1;
}

void DisplayTable(vector<vector<int>>& table)
{
	vector<vector<int>>::const_iterator it1;
	vector<int>::const_iterator it2;
	for (it1 = table.begin(); it1 != table.end();++it1)
	{
		for (it2 = (*it1).begin(); it2 != (*it1).end();++it2)
		{
			cout << *it2 << ' ';
		}
		cout << endl;
	}
}

void dfs(int i, vector<vector<int>>& table, vector<int>& status)
{
	if (i == VERTEXNUM)
		return;

	if (status[i] == 0)
	{
		cout << i << " ";
		status[i] = 1;
	}
	for (int j = 0; j < VERTEXNUM;++j)
	{
		if (status[j]==0&&table[i][j]==1)
		{
			status[j] = 1;
			cout << j << " ";
			dfs(j, table, status);
		}
	}
}

int main(void)
{
	vector<vector<int>> table(VERTEXNUM, vector<int>(VERTEXNUM, 0));
	vector<int> status(VERTEXNUM, 0);

	CreateTable(table, 0, 3);
	CreateTable(table, 0, 4);
	CreateTable(table, 3, 1);
	CreateTable(table, 3, 2);
	CreateTable(table, 4, 1);

	DisplayTable(table);

	for (int i = 0; i < VERTEXNUM;++i)
	{
		if (status[i]==0)
		{
			dfs(i, table, status);
		}
	}
	cout << endl;

	return 0;
}

运行结果:


代码说明:

1 main函数中的for循环是为了防止非连通图的出现。

2 dfs中j要从0开始,而不是i。第二个if就是为了防止重复访问。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值