算法导论 第二十二章:图的搜索

图有两种标准的表示方法,即邻接矩阵和邻接表(通常邻接矩阵用于稠密图,邻接表用于稀疏图)。如下:

对于图的搜索有两种方法:深度优先搜索 & 广度优先搜索。


广度优先搜索(Breadth-first search)

     广度优先搜索是将已发现和未发现顶点之间的边界沿其广度方向向外扩展。亦即算法首先会发现和s距离为k的所有点,然后才会发现和s距离为k+1的其他顶点。

伪代码:

EG:

运行时间:O(V+E)。

深度优先遍历(Depth-first search)

        在深度优先搜索中,对于最新发现的顶点,如果他还有以此为起点而为探测到的变,就沿着此边继续探测下去。当顶点v的所有变都已被探寻后,搜索将回溯到发现顶点v有起始点那条边。

伪代码:

EG:


运行时间:O(V+E).

========================================================================================================================

广度优先搜索完整代码:

#include<iostream>
#include<queue>
#include<climits>
#define UDG 0
#define DG  1

#define WHITE 2
#define GRAY  3
#define BLACK 4

using namespace std;

typedef char vType;
typedef struct gEdge{
	vType adjVertex;   //the adjacency vertex pointed by this edge.
	int weight;        //the weight of this edge
	gEdge *nextEdge;   //Point to the next edge
	}gEdge;

typedef struct gVertex{
	vType key;         // the key of the vertex
	int color;
	int d;
	vType pai;
	gEdge *firstEdge;  // point to the first edge attached to the vertex;
	}gVertex;
typedef struct ALGraph{
	int Vnum;
	int Enum;
	int kind;   //the kind of Graph 
	gVertex *HeadVertex;	
	}ALGraph;

typedef struct edge{
	vType start;
	vType end;
	}edge;
int Locate(ALGraph &G,vType s)
{//locate the start vertex of one edge in head vertex of the graph
	for(int i=0;i<G.Vnum;i++)
		if(G.HeadVertex[i].key == s)
			return i;
	return -1;
	}
void LinkEdgeToGraph(ALGraph &G, edge e)
{
		gEdge *arc=new gEdge();
		arc->adjVertex=e.end;

		int headV_i=Locate(G,e.start);
			
		arc->nextEdge=G.HeadVertex[headV_i].firstEdge;
		G.HeadVertex[headV_i].firstEdge = arc;
	}
void Graph_Create(ALGraph &G, vType V[], edge E[])
{
	//init the head vertex
	G.HeadVertex= new gVertex[G.Vnum];
	for(int i=0;i<G.Vnum;i++){
		G.HeadVertex[i].key=V[i];
		G.HeadVertex[i].firstEdge=NULL;
	}  

	//add edge to head vertex in order to create a graph
	if(G.kind == DG) //undirected graph
		for(int i=0; i<G.Enum; i++)
			LinkEdgeToGraph(G,E[i]);
	if(G.kind == UDG) // directed graph
		for(int i=0; i<G.Enum; i++)
		{ 
			LinkEdgeToGraph(G,E[i]);
			// link again after reversed
			edge temp;
			temp.start = E[i].end;
			temp.end   = E[i].start;
			LinkEdgeToGraph(G,temp);
		 	}
	}
void Graph_Print(ALGraph G)
{
	for(int i=0; i<G.Vnum; i++)
	{ 
		cout<<G.HeadVertex[i].key;
		gEdge *p = G.HeadVertex[i].firstEdge;
		while(p != NULL)
		{
			cout<<" -->  "<< p->adjVertex;
			p = p->nextEdge;
  			}  
		cout<<endl;
  		}
	}
/*
void Q_Print(queue<vType> Q)
{
	cout<<"The Q is:";
	while(!Q.empty())
	{
		cout<<Q.front()<<"  ";
		Q.pop();
		}
	cout<<endl;
	}
*/
vType *ALGraph_BFS(ALGraph &G, vType s)
{
	queue<vType> Q;
	
	vType *BFSResult=new vType[G.Vnum];
	
	//label the vertex:the starting vertex becomes GRAY,the others become WHITE...
	for(int i=0; i<G.Vnum; i++)
	{
		gVertex *hVertex=&G.HeadVertex[i];
		hVertex->color = WHITE;
		hVertex->d = INT_MAX;
		hVertex->pai = '0';
		if(hVertex->key == s)
		{ 
			hVertex->color = GRAY;
			hVertex->d = 0;
			} 
		}

	//Clear the Q
	while(!Q.empty())  // making the queue Q empty
		Q.pop();
	Q.push(s);        // s enter queue Q
	
	//Searching layer by layer
	int r_i=0;
	while(!Q.empty())
	{
		vType u,v;
		u= Q.front();Q.pop();  //delete the front element of the Q

		BFSResult[r_i] = u;    //store the result into Array BFSResult
		r_i++;

		int h_i=Locate(G,u);
		gVertex *hu = &G.HeadVertex[h_i];
		gEdge *p = G.HeadVertex[h_i].firstEdge;
		while(p)
		{
			v = p->adjVertex;
			
			h_i = Locate(G,v);
			gVertex *hv = &G.HeadVertex[h_i];
			if(hv->color == WHITE)
			{ 
				hv->color = GRAY;
				hv->d = hv->d+1;
				hv->pai = u;
				Q.push(v);
	 		 	} 
			p = p->nextEdge;
	 		} 
		hu->color = BLACK;
	 	}
	return BFSResult;
	}
int main()
{
	vType V[]={'s','w','r','v','t','x','u','y'};
	edge  E[]={{'r','v'},{'r','s'},{'s','w'},{'w','t'},{'w','x'},{'t','u'},{'t','x'},{'x','u'},{'x','y'},{'u','y'}};
	ALGraph G;
	
	G.Vnum=sizeof(V)/sizeof(vType);
	G.Enum=sizeof(E)/sizeof(edge);
	G.kind=UDG;           //the kind of Graph

	Graph_Create(G,V,E);
	cout<<"---------------Create Graph-----------------"<<endl;
	cout<<"The created graph is:"<<endl;
	Graph_Print(G);

	cout<<"---------------BFS Graph--------------------"<<endl;
	cout<<"Please input the starting position:";
	vType s;
	cin>>s;
	vType *BFSResult = new vType[G.Vnum];
	BFSResult=ALGraph_BFS(G,s);
	cout<<"The result of BFS is:"<<endl;
	for(int i=0; i<G.Vnum; i++)
		cout<<BFSResult[i]<<"   ";
	cout<<endl;



	return 0;
	}


运行结果:


深度优先搜索完整代码:

#include<iostream>
#include<iomanip>
using namespace std;

#define UDG 0
#define DG  1

#define WHITE 0  
#define GRAY  1  
#define BLACK 2  
  
#define NONE 0  
#define TREE 1  
#define BACK 2  
#define FORWARD 3  
#define CROSS 4 


typedef char vType;
typedef struct gEdge{
	vType adjVertex;   //the adjacency vertex pointed by this edge.
	int weight;        //the weight of this edge
	int type;          //the type of edge
	gEdge *nextEdge;   //Point to the next edge
	}gEdge;

typedef struct gVertex{
	vType key;         // the key of the vertex
	int color;
	int d,f;           // the discovered time and the finished time
	vType pai;         // the parent node's key after searching
	gEdge *firstEdge;  // point to the first edge attached to the vertex;
	}gVertex;
typedef struct ALGraph{
	int Vnum;
	int Enum;
	int kind;   //the kind of Graph 
	gVertex *HeadVertex;	
	}ALGraph;

typedef struct edge{
	vType start;
	vType end;
	}edge;
int Locate(ALGraph &G,vType s)
{//locate the start vertex of one edge in head vertex of the graph
	for(int i=0;i<G.Vnum;i++)
		if(G.HeadVertex[i].key == s)
			return i;
	return -1;
	}
void LinkEdgeToGraph(ALGraph &G, edge e)
{
		gEdge *arc=new gEdge();
		arc->adjVertex=e.end;

		int headV_i=Locate(G,e.start);
			
		arc->nextEdge=G.HeadVertex[headV_i].firstEdge;
		G.HeadVertex[headV_i].firstEdge = arc;
	}
void Graph_Create(ALGraph &G, vType V[], edge E[])
{
	//init the head vertex
	G.HeadVertex= new gVertex[G.Vnum];
	for(int i=0;i<G.Vnum;i++){
		G.HeadVertex[i].key=V[i];
		G.HeadVertex[i].firstEdge=NULL;
	}   

	//add edge to head vertex in order to create a graph
	if(G.kind == DG) //undirected graph
		for(int i=0; i<G.Enum; i++)
			LinkEdgeToGraph(G,E[i]);
	if(G.kind == UDG) // directed graph
		for(int i=0; i<G.Enum; i++)
		{
			LinkEdgeToGraph(G,E[i]);
			// link again after reversed
			edge temp;
			temp.start = E[i].end;
			temp.end   = E[i].start;
			LinkEdgeToGraph(G,temp);
		 	}
	}
void Graph_Print(ALGraph G)
{
	for(int i=0; i<G.Vnum; i++)
	{ 
		cout<<G.HeadVertex[i].key;
		gEdge *p = G.HeadVertex[i].firstEdge;
		while(p != NULL)
		{
			cout<<" -->  "<< p->adjVertex;
			p = p->nextEdge;
 		 	}  
		cout<<endl;
 		 }
	}

void EdgeType_Print(ALGraph G)
{
	for(int i=0; i<G.Vnum; i++)
	{
		gEdge *p = G.HeadVertex[i].firstEdge;
		while(p)
		{
			cout<<G.HeadVertex[i].key<<"-->"<<p->adjVertex<<":";
			switch(p->type)
			{
				case TREE:
					cout<<"Tree edge"<<endl;
					break;
				case BACK:
					cout<<"Back edge"<<endl;
					break;
				case FORWARD:
					cout<<"Forward edge"<<endl;
					break;
				case CROSS:
					cout<<"Cross edge"<<endl;
					break;
				}
			p = p->nextEdge;
			}
		}
	}


/*--------------------DFS Alogithms-----------------------*/
int time0;
int r_i=0;
void Graph_DFSVisit(ALGraph &G, gVertex *u, vType *r)
{
	time0 = time0 +1;  //white vertex u has just been discovered
	u->d = time0 ;
	u->color = GRAY;
	

	gEdge *p = u->firstEdge;
	while(p)
	{ 
		vType v = p->adjVertex;
		int h_i=Locate(G,v);
		gVertex *hv = &G.HeadVertex[h_i];
		
		//classify the edge and recursive searching
		if( hv->color == WHITE)
	 	{ 
			hv->pai = u->key;
			Graph_DFSVisit(G,hv,r);
			p->type = TREE;        //Tree edge
			}
		else if(hv->color == GRAY){
			p->type = BACK;        //Back edge
		}
		else if(hv->color == BLACK)
		{
			if(u->d < hv->d)
				p->type = FORWARD; //Forward edge
			else
				p->type = CROSS;  //Cross edge
			}
		p = p->nextEdge;
		}

	u->color = BLACK;  //backen u;it is finished
	r[r_i++]=u->key;   //store the dfs result into array r

	time0 = time0 +1;
	u->f = time0;
}
void ALGraph_DFS(ALGraph &G, vType *result)
{
	//init all the vertex
	gVertex *u;
	for(int i=0; i<G.Vnum; i++)
	{
		u = &G.HeadVertex[i];
		u->color = WHITE;
		u->pai = '0';
		} 
	time0 = 0;  //time stamp
	
	//explore every vertex
	for(int i=0; i<G.Vnum; i++)
	 {
		u = &G.HeadVertex[i];
		if(u->color == WHITE)
			Graph_DFSVisit(G,u,result);
		} 
	}
/*----------------------------------------------*/
int main()
{
	vType V[]={'u','x','v','y','w','z'};
	edge  E[]={{'u','x'},{'u','v'},{'x','v'},{'v','y'},{'y','x'},{'w','y'},{'w','z'},{'z','z'}};
	ALGraph G;
	
	G.Vnum=sizeof(V)/sizeof(vType);
	G.Enum=sizeof(E)/sizeof(edge);
	G.kind=DG;           //the kind of Graph

	Graph_Create(G,V,E);
	cout<<"---------------Create Graph-----------------"<<endl;
	cout<<"The created graph is:"<<endl;
	Graph_Print(G);

	cout<<"---------------DFS Graph--------------------"<<endl;
	vType *DFSResult = new vType[G.Vnum];
	ALGraph_DFS(G,DFSResult);
	cout<<"The result of DFS is:"<<endl;
	for(int i=0; i<G.Vnum; i++)
		cout<<DFSResult[i]<<"   ";
	cout<<endl;
	cout<<"The discovered time and finished time respectivly is:"<<endl;
	for(int i=0; i<G.Vnum; i++)
		cout<<G.HeadVertex[i].key<<setw(4)<<G.HeadVertex[i].d<<setw(4)<<G.HeadVertex[i].f<<endl;
	cout<<"The Edge type information is:"<<endl;
	EdgeType_Print(G);
	cout<<"--------------------------------------------"<<endl;
	return 0;
	}

运行结果:


【注:若有错误,请指正~~~】

目录(Table of Contents)   前言(Preface)   第一部分(Part I) 基础(Foundations)   第一 计算中算法的角色(The Role of Algorithms in Computing)   第二 开始(Getting Started)   第三 函数的增长率(Growth of Functions)   第四 递归(Recurrences)   第五 概率分析与随机化算法(Probabilistic Analysis and Randomized Algorithms)   第二部分(Part II) 排序与顺序统计(Sorting and Order Statistics)   第六 堆排序(Heapsort)   第七 快速排序(Quicksort)   第八 线性时间中的排序(Sorting in Linear Time)   第九 中值与顺序统计(Medians and Order Statistics)   第三部分(Part III) 数据结构(Data Structures)   第十 基本的数据结构(Elementary Data Structures)   第十一 散列表(Hash Tables)   第十二 二叉查找树(Binary Search Trees)   第十三 红-黑树(Red-Black Trees)   第十四 扩充的数据结构(Augmenting Data Structures)   第四部分(Part IV) 高级的设计与分析技术(Advanced Design and Analysis Techniques)   第十五 动态规划(Dynamic Programming)   第十六 贪婪算法(Greedy Algorithms)   第十七 分摊分析(Amortized Analysis)   第五部分(Part V) 高级的数据结构(Advanced Data Structures)   第十八 B-树(B-Trees)   第十九 二项式堆(Binomial Heaps)   第二十 斐波纳契堆(Fibonacci Heaps)   第二十一 不相交集的数据结构(Data Structures for Disjoint Sets)   第六部分(Part VI) 算法(Graph Algorithms)   第二十二章 基本的算法(Elementary Graph Algorithms)   第二十三 最小生成树(Minimum Spanning Trees)   第二十四 单源最短路径(Single-Source Shortest Paths)   第二十五 全对的最短路径(All-Pairs Shortest Paths)   第二十六 最大流(Maximum Flow)   第七部分(Part VII) 精选的主题(Selected Topics)   第二十七 排序网络(Sorting Networks)   第二十八 矩阵运算(Matrix Operations)   第二十九 线性规划(Linear Programming)   第三十 多项式与快速傅里叶变换(Polynomials and the FFT)   第三十一 数论算法(Number-Theoretic Algorithms)   第三十二 字符串匹配(String Matching) ......................................................
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值