图的遍历

来源:互联网 发布:json转换为字符串 编辑:程序博客网 时间:2024/05/29 15:59

图的遍历有两种遍历方式:深度优先遍历(depth-first search)和广度优先遍历(breadth-first search)

深度优先遍历

基本思想:首先从图中某个顶点v0出发,访问此顶点,然后依次从v0相邻的顶点出发深度优先遍历,直至图中所有与v0路径相通的顶点都被访问了;若此时尚有顶点未被访问,则从中选一个顶点作为起始点,重复上述过程,直到所有的顶点都被访问。可以看出深度优先遍历是一个递归的过程。
深度优先搜索和树的先序遍历很相似,可以回顾树的先序遍历过程来帮助自己理解,也可以参考一下这个链接里面的演示。

广度优先遍历

基本思想:首先,从图的某个顶点v0出发,访问了v0之后,依次访问与v0相邻的未被访问的顶点,然后分别从这些顶点出发,广度优先遍历,直至所有的顶点都被访问完。


这里贴出两种遍历方式的C++代码,深度遍历分别用递归和非递归的方式实现,图是用邻接表表示。
需要注意的是,深度遍历的非递归方式代码中,使用反向迭代器来遍历一个节点的邻接点,这样做的目的是为了将节点的邻接点逆序入栈,这样才能顺序出栈,这和采用非递归方式先序遍历树时先将右孩子入栈的道理是一样的。

//图的深度搜索和广度搜索#include "stdafx.h"#include <iostream>#include<stack>#include<vector>#include<list>#include<queue>using namespace std;namespace BFSandDFS_LinJieBiao{const int  MAX = 100;bool visited[MAX];vector<list<int>>graph;//采用邻接表表示的图void clearVisited(){for (int i = 0; i < MAX; i++)visited[i] = false;}void BFS(int v)//广度搜索,使用队列{list<int>::iteratoriter;visited[v] = true;cout << v << " ";queue<int> quu;quu.push(v);while (!quu.empty()){v = quu.front();quu.pop();for (iter = graph[v].begin(); iter != graph[v].end(); iter++){if (!visited[*iter]){quu.push(*iter);cout << (*iter) << " ";visited[*iter] = true;}}}cout << endl;}//深度优先搜索遍历类似于树的先序遍历void DFS(int v)//采用递归实现深度遍历{list<int>::iteratoriter;visited[v] = true;cout << v << ' ';for (iter = graph[v].begin(); iter != graph[v].end(); iter++)if (!visited[*iter]){visited[*iter] = true;DFS(*iter);}}void DFS_NonRecursive(int v)//采用非递归的方式进行深度搜索{list<int>::reverse_iterator riter;//采用反向迭代器stack<int> s;s.push(v);while (!s.empty()){v = s.top();s.pop();if (!visited[v]){cout << v << ' ';visited[v] = true;for (riter = graph[v].rbegin(); riter != graph[v].rend(); riter++)if (!visited[*riter])s.push(*riter);}}}void test(){//构造邻接表graph.resize(8);graph[0].push_back(1);graph[0].push_back(2);graph[1].push_back(0);graph[1].push_back(3);graph[1].push_back(4);graph[2].push_back(0);graph[2].push_back(5);graph[2].push_back(6);graph[3].push_back(1);graph[3].push_back(7);graph[4].push_back(1);graph[4].push_back(7);graph[5].push_back(2);graph[5].push_back(6);graph[6].push_back(2);graph[6].push_back(5);graph[7].push_back(3);graph[7].push_back(4);cout << " DFS递归方式:" << endl;DFS(0);cout << endl;clearVisited();cout << "DFS非递归方式:" << endl;DFS_NonRecursive(0);cout << endl;clearVisited();cout << "BFS:" << endl;BFS(0);cout << endl;}}/********************************************************************/int _tmain(int argc, _TCHAR* argv[]){BFSandDFS_LinJieBiao::test();return 0;}


采用邻接表方式构造一个这样的图:


程序运行结果:


在用邻接矩阵表示图的情况下的C++代码,程序差别不大:

#include "stdafx.h"#include <iostream>#include<stack>#include<vector>#include<list>#include<queue>using namespace std;namespace BFSandDFS_LinJieJuzhen{const int MAX = 100;struct Graph{int e[MAX][MAX];//邻接矩阵int vertexs;//顶点数int edges;//边个数};Graph graph;int visited[MAX];void clearVisited(){for (int i = 0; i < MAX; i++)visited[i] = false;}void createGraph(){for (int i = 0; i < graph.vertexs;i++)for (int j = 0; j < graph.vertexs; j++)graph.e[i][j] = 0;graph.vertexs = 8;graph.e[0][1] = 1;graph.e[0][3] = 1;graph.e[0][4] = 1;graph.e[1][0] = 1;graph.e[1][4] = 1;graph.e[1][2] = 1;graph.e[2][1] = 1;graph.e[2][5] = 1;graph.e[3][0] = 1;graph.e[3][6] = 1;graph.e[4][0] = 1;graph.e[4][1] = 1;graph.e[4][6] = 1;graph.e[5][2] = 1;graph.e[6][3] = 1;graph.e[6][4] = 1;graph.e[6][7] = 1;graph.e[7][6] = 1;}void BFS(int v){queue<int> quu;quu.push(v);visited[v] = true;//这里入队即访问,只在每个元素入队的时候修改visited为truewhile (!quu.empty()){v = quu.front();quu.pop();cout << v << ' ';for (int i = 0; i < graph.vertexs; i++){if (graph.e[v][i] != 0 && !visited[i]){quu.push(i);visited[i] = true; }}}cout << endl;}void DFS(int v)//递归{cout << v << ' ';visited[v] = true;for (int i = 0; i < graph.vertexs; i++){if (!visited[i] && graph.e[v][i] != 0)DFS(i);}}void DFS_NonRecursive(int v){stack<int> s;int i = 0;s.push(v);while (!s.empty()){v = s.top();s.pop();if (!visited[v]){visited[v] = true;cout << v << ' ';for (int i = graph.vertexs; i >= 0; i--){if (!visited[i] && graph.e[v][i] != 0){s.push(i);}}}}cout << endl;}void test(){createGraph();clearVisited();cout << "BFS result:" << endl;BFS(0);clearVisited();cout << "DFS 递归 result:" << endl;DFS(0);clearVisited();cout<<endl << "DFS 非递归 result:" << endl;DFS_NonRecursive(0);}}int _tmain(int argc, _TCHAR* argv[]){BFSandDFS_LinJieJuzhen::test();return 0;}
遍历的图如下:

运行结果:





0 0
原创粉丝点击