图的深度优先遍历(递归与非递归算法)和广度优先遍历

老师的题目::

实验内容

已知某地区的公路网以图表示,图中的顶点表示站点,任意两站点间的路段以带权的边构成的邻接矩阵表示,矩阵中非零元表示两个站点间存在直接的路段,否则没有路段。

打开E:\Test文件夹中的exp06.cpp文件,补充编写所需代码。程序首先进行图的连通性判定,若图连通则输出连通信息,否则继续计算和输出图的连通分量数。

输入数据在文件exp06.in中,首行的整数是站点的总数n(1<n<=30);第2行开始的n行中,每行n个整数,是这n个站点构成的公路网的邻接矩阵。例如,

6

01 3 4 9 0

10 9 9 0 0

39 0 0 6 8

49 0 0 5 7

90 6 5 0 4

00 8 7 4 0

主函数中,在调用读入数据函数readData()时,会自动将矩阵中的零元(除对角线保持0以外)替换成无穷大(9999)。

Search(intv)函数实现从顶点v出发的一次搜索过程,并累计访问顶点数。

若图是连通的,则输出文件exp06.out中包含如下文字:

All vertexsare connected.

否则,计算和输出连通分量数,输出文件的内容则如下例:

    The number of connected components is 2.

解题思路

利用一次深度优先或者广度优先搜索过程中对访问顶点数的计数,并判断其与图的顶点总数是否相等来判定图的连通性。

如果图不连通,则继续从下一个未被访问的顶点出发再进行一次搜索,如此反复,直到已遍历图的所有顶点,累计的搜索次数即是图的连通分量数。

我在代码中都做了注解

#include <iostream>
#include <stdio.h>
using namespace std;

const int Size=30;
const double INF=9999;		// infinity (无穷大)
int vexnum;					// total number of vertex (顶点总数) 
int adjmat[Size][Size];		// adjacent matrix (邻接矩阵)
int mark[Size];				// vector of visiting mark of vertex (顶点访问标记向量)
int visitnum;				// number of visited vertex for one search (一次搜索中被访问顶点数)
int adjnum;					// number of connected components (连通分量数) 

void readData()
{	int i,j;
	cin>>vexnum;			// input vexnum 
	for(i=0; i<vexnum; i++)
		for(j=0; j<vexnum; j++)
		{	cin>>adjmat[i][j];
			if(i!=j && adjmat[i][j]==0) adjmat[i][j]=INF;
		}
}
/*int first_adj(int v){
	int w;
	for(w=0;w<vexnum;w++)
		if(adjmat[v][w]!=INF||v!=w) return w;
	return -1;	
}
int next_adj(int v,int w){
	for(w+=1;w<vexnum;w++)
		if(adjmat[v][w]!=INF||v!=w) return w;
	return -1;	
}*/
void Search(int v)			// one time search, v represents the starting vertex
{//************************************************
	//********************************************
	/*int w=-1;   //书上的解法,太麻烦了
	mark[v]=1;
	visitnum++;
	w=first_adj(v);
	while(w!=-1){
		if(!mark[w])
			Search(w);
		w=next_adj(v,w);
	}*/
	//==============================================
	

	//**************************************************
	/*递归的深度优先搜索
	int i;
	if(mark[v]==1) return;   //访问过了,要有,可用于判断连通分量
	mark[v]=1;   //否则访问他
	visitnum++;
	for(i=0;i<vexnum;i++){
		if(adjmat[v][i]!=INF&&v!=i&&mark[i]!=1)   //找到未访问过的邻接点
			Search(i);
	}
	return;*/
	//====================================================





	//***************************************************
	/*
	//非递归的深度优先搜索
	int *stack=new int[vexnum],top=-1,w;
	if(mark[v]==1) return;
	stack[++top]=v;
	mark[v]=1;
	visitnum++;
	while(top!=-1){
		v=stack[top];         //不能top--,因为后面还要用到此处节点
		for(w=0;w<vexnum;w++){//找一个未访问的邻接点,可以使用上面的first_adj(v)
			if(adjmat[v][w]!=INF && v!=w && mark[w]!=1)
				break;
		}
		if(w==vexnum) top--;  //此节点   没有   还没找过的邻接点了,退栈
		else{					//有未访问邻接点,人栈,接下来从这个节点继续深度访问
			stack[++top]=w;	
			mark[w]=1;
			visitnum++;
		}
	}
	*/
	//=====================================================


	//*******************************************
	/*
	//广度优先搜索   先访问再入队
	int *queue=new int[vexnum+1],front=0,rear=0;
	int w;
	if(mark[v]==1) return;   
	mark[v]=1;	
	visitnum++;
	queue[rear++]=v;
	while(front!=rear){
		v=queue[front++];
		for(w=0;w<vexnum;w++){   //找到所有未访问邻接点入队
			if(adjmat[v][w]!=INF&&v!=w&&mark[w]!=1){
				queue[rear++]=w;
				mark[w]=1;
				visitnum++;
			}
		}
		//找完了
	}
	//========================================
	*/
 //================================================
}

int main()
{	int i;
/*	freopen("exp06.in", "r", stdin);
	freopen("exp06.out", "w", stdout);*/
	readData();							// input data 
	for(i=0; i<vexnum; i++) mark[i]=0;	// initialze the visiting mark
	visitnum=0;
	Search(0);							// one time search from vertex 0 
	if(visitnum==vexnum) cout<<"All vertexs are connected.\n";
	else 
	{	adjnum=1;
		//************************************************
	for(i=0;i<vexnum;i++){
		if(!mark[i]){
			Search(i);
			adjnum++;
		}
	}
 		//================================================
		cout<<"The number of connected components is "<<adjnum<<".\n";
	}
	return 0;
}

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/Mojard/article/details/72792913
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞