1. 程式人生 > >演算法導論 第二十二章:拓撲排序

演算法導論 第二十二章:拓撲排序

拓撲排序(針對有向無迴路圖DAG)是深度優先搜尋的一個應用,其結果圖中所有頂點的一個線性排列。

虛擬碼如下:


EG:

拓撲排序完整程式碼如下:

#include<iostream>
#include<iomanip>
#include<string>
#include<algorithm>
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 string 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 ALGraph_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);
		} 
	}
/*------------------------------------------------------*/

/*-----------------Topological Sort--------------------*/
bool compare(const gVertex &a,const gVertex &b)
{
	return a.f > b.f;           //descending order 
	}
void ALGraph_TSort(ALGraph &G, vType *result)
{
	ALGraph_DFS(G,result);

	//sorting the finished time in descending order
	sort(G.HeadVertex,G.HeadVertex+G.Vnum,compare);  //call the system's sorting function:
	
	//store the result 
	int r_i=0;
	for(int i=0; i<G.Vnum;i++)
		result[r_i++] = G.HeadVertex[i].key;
	}
/*---------------------------------------------------*/
int main()
{

	vType V[]={"shirt","tie","jacket","belt","watch","undershorts","pants","shoes","socks"};
	edge  E[]={{"shirt","belt"},{"shirt","tie"},{"tie","jacket"},{"belt","jacket"},{"pants","belt"},{"pants","shoes"},{"undershorts","shoes"},{"undershorts","pants"},{"socks","shoes"}};
	
	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;
	ALGraph_Print(G);
	cout<<"--------------Toplogical sort-----------------"<<endl;
	vType *TSortResult = new vType[G.Vnum];
	ALGraph_TSort(G,TSortResult);
	cout<<"The result of Topological sort is:"<<endl;
	for(int i=0; i<G.Vnum; i++)
		cout<<setw(11)<<TSortResult[i]<<":"<<setw(3)<<G.HeadVertex[i].d<<setw(3)<<G.HeadVertex[i].f<<endl;
	cout<<"----------------------------------------------"<<endl;
	return 0;
	}

執行結果:
<img src="https://img-blog.csdn.net/20150720015422746" alt="" />