关于BFS&DFS的代码实现和算法描述

107 阅读2分钟

算法描述

关于深度优先遍历(DFS)和广度优先遍历(BFS)的遍历方式大体一致:

  • 选择某一个顶点作为起始点 —— 函数xxxTraverse()

  • 若改点未被访问过,即visit[i]=0时,则将其放入栈/队列

  • 当栈/队列不为空时,弹出top(栈)/front(队列)元素,并判断其是否被访问过

  • 如果没有则输出,并将其状态改为已访问,即visit[i]=1,之后对该元素的邻居进行循环遍历(for)

  • 重新返回Step.2,直到栈/队列为空,完成遍历

DFS代码实现

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stack>
using namespace std;
class Graph
{
	bool* visit;
	int** adjMatrix;
	int vernum;
	//stack<int>*s;
public:
	Graph()
	{
		cin >> vernum;
		adjMatrix = new int* [vernum];
		visit = new bool[vernum];
		//s = new stack<int>[vernum];
		for (int i = 0; i < vernum; i++)
		{
			adjMatrix[i] = new int[vernum];
			visit[i] = false;
			for (int j = 0; j < vernum; j++)
			{
				cin >> adjMatrix[i][j];
			}
		}
	}
	~Graph()
	{
		for (int i = 0; i < vernum; i++)
		{
			delete[]adjMatrix[i];
		}
		delete[]adjMatrix;
		delete[]visit;
	}
    
	//递归——除了用栈,递归也是一种解决方法,不过由于复杂度问题,一般更推荐使用栈
	//void DFS(int i)
	//{
	//	cout << i << " ";
	//	visit[i] = true;
	//	for (int j = 0; j < vernum; j++)
	//	{
	//		if (adjMatrix[i][j] && !visit[j])DFS(j);
	//	}
	//}
	//void DFSTraverse()//从顶点开始遍历
	//{
	//	for (int i = 0; i < vernum; i++)
	//	{
	//		if (!visit[i])DFS(i);
	//	}
	//	cout << endl;
	//}


	//栈实现
	void DFS_iter(int i)
	{
		s->push(i);
		while (s->size() > 0)
		{
			i = s->top();
			s->pop();
			if (!visit[i])
			{
				cout  << i << " ";
				visit[i] = true;
				for (int j = 0; j < vernum; j++)
				{
					if (adjMatrix[i][j]&&!visit[j])s->push(j);
				}
			}
		}
	}
	void DFS_iterTraverse()
	{
		for (int i = 0; i < vernum; i++)
		{
			if (!visit[i])DFS_iter(i);
		}
	}

};
int main()
{
	int t;
	Graph g;
	g.DFS_iterTraverse();
}

BFS代码实现

#include<iostream>
#include<queue>
using namespace std;
class Graph
{
	bool* visit;
	int** adjMatrix;
	int verNum;
	queue<int>* q;
public:
	Graph()
	{
		cin >> verNum;
		visit = new bool[verNum];
		adjMatrix = new int* [verNum];
		q = new queue<int>[verNum];
		for (int i = 0; i < verNum; i++)
		{
			adjMatrix[i] = new int[verNum];
			visit[i] = false;
			for (int j = 0; j < verNum; j++)
			{
				cin >> adjMatrix[i][j];
			}
		}
	}
	~Graph()
	{
		for (int i = 0; i < verNum; i++)
		{
			delete[]adjMatrix[i];
		}
		delete[]visit;
		delete[]adjMatrix;
	}
	void BFS_Traverse()
	{
		for (int i = 0; i < verNum; i++)
		{
			if (!visit[i])BFS(i);
		}
	}
	void BFS(int i)
	{
		q->push(i);
		while (q->size() > 0)
		{
			i = q->front();
			q->pop();
			if (!visit[i])
			{
				cout << i << " ";
				visit[i] = true;
				for (int j = 0; j < verNum; j++)
				{
					if (!visit[j] && adjMatrix[i][j])q->push(j);
				}
			}
		}
	}
};
int main()
{	
	Graph g;
	g.BFS_Traverse();
}

碎碎念

我一开始学这两个遍历时,总是搞不懂里面的逻辑:为什么一个用栈,而另一个用队列?为什么要创建visit数组?怎样才能访问顶点的邻居......后面静下心来,找了几个视频看,并跟着里面的伪代码编写可运行代码,总算摸索出一点门道来。所以当遇到问题时,不要想着逃避,或许静下心来思考,或许能擦出点火花~ 若有不足,欢迎指出~