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

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

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


广度优先搜索(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;
	}

运行结果:


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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值