1、广度优先遍历
原理:
广度优先遍历从某个顶点v出发,首先访问这个结点,并将其标记为已访问过;
然后顺序访问结点v的所有未被访问的邻接点{vi,..,vj},并将其标记为已访问过;
然后将{vi,...,vj}中的每一个节点重复节点v的访问方法,直到所有结点都被访问完为止。
具体代码实现时:
我们可以使用一个辅助队列q,首先将顶点v入队,将其标记为已访问,然后循环检测队列是否为空;
如果队列不为空,则取出队列第一个元素,并将与该元素相关联的所有未被访问的节点入队,将这些节点标记为已访问;
如果队列为空,则说明已经按照广度优先遍历了所有的节点。
2、深度优先遍历
思路:
深度优先遍历首先从某个顶点v出发,并将其标记为已访问过;
然后搜索(而不是访问)v的每个邻接点,得到w={vi,...,vj},顺序以w中的每个节点为出发点继续进行深度优先遍历,直到所有结点都被访问完为止。
具体代码实现时:
我们可以使用一个辅助栈s,首先将顶点v入栈,将其标记为已访问,然后循环检测栈是否为空;
如果栈不为空,我们首先判断是否已经遍历到了最图的最深处,如果不是则继续遍历节点并入栈,并将其标记为已访问,否则说明已经遍历到了图的最深处,此时弹出栈顶元素,将与栈顶元素相关联的所有未访问的元素进栈。
如果栈为空,则说明已经按照深度优先遍历了所有的节点。
3、两种遍历的非递归代码如下:
#include "stdafx.h" #include <iostream.h> #include <stdlib.h> #include <queue> #include <stack> using namespace std; const int n=9; //广度优先遍历 void BFS(int a[][n]) { //label数组标记访问元素 int label[n+1]; for (int j=0;j<=n;j++) label[j]=0; queue<int> q; q.push(0); label[0]=1; //标记已访问元素 //队列不为空 while(!q.empty()) { int key=q.front(); cout<<key<<" "; q.pop(); //将与key节点相关联的未访问的节点入队 for (int i=0;i<n;i++) { if (a[key][i]!=0&&label[i]==0) { q.push(i); label[i]=1; //标记已访问元素 } } } cout<<endl; } //元素入栈,并标记已访问元素,同时更新flag void PushNode(int a[][n],stack<int> s,int *label,int &key,int &flag) { for (int i=0;i<n;i++) { flag=key; if (a[key][i]!=0&&label[i]==0) { s.push(i); label[i]=1; key=i; break; } } } //深度优先遍历 void DFS(int a[][n]) { //label数组标记访问元素 int *label=new int[n+1]; for (int j=0;j<=n;j++) label[j]=0; stack<int> s; int key=0; int flag=-1; //用flag变量判断是否已经遍历到最底端 s.push(key); label[key]=1; while(!s.empty()) { //未遍历到图的最深处 if(key!=flag) { cout<<key<<" "; PushNode(a,s,label,key,flag); } //遍历到图的最深处 else { key=s.top(); s.pop(); PushNode(a,s,label,key,flag); } } cout<<endl; delete label; } int main(int argc, char* argv[]) { //邻接矩阵9*9,节点0~8 int a[n][n]={ 1,1,0,0,1,1,1,1,0, 1,1,0,1,0,0,1,1,1, 0,0,1,1,0,1,1,0,1, 0,1,1,1,1,1,1,0,0, 1,0,0,1,1,0,1,1,0, 1,0,1,1,0,1,1,1,1, 1,1,1,1,1,1,1,0,1, 1,1,0,0,1,1,0,1,1, 0,1,1,0,0,1,1,1,1 }; cout<<"广度优先遍历:"; BFS(a); cout<<"深度优先遍历:"; DFS(a); return 0; }