图论----深度优先遍历和广度优先遍历

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;
}

 

你可能感兴趣的:(ini)