1. 程式人生 > >圖(有向圖)的應用——拓撲排序

圖(有向圖)的應用——拓撲排序

1、基本概念:

有序圖,每個頂點都有前驅和後繼的關係。

現實生活中我們可以用一個有向圖來表示一個工程,頂點表是活動,有向邊A---------->B表示:A必須先於活動B進行。這種有向圖叫做“  頂表示活動的網路(activity  on  vertices)”

——記作AOV網路。

將全部頂點都排在一個線性有序的序列中。這種構造AOV網路全部頂點的拓撲有序序列的運算就叫做拓撲排序(topological  sorting)

2、步驟:

(1)選擇一個沒有直接前驅的頂點,並輸出;

(2)從圖中刪除該頂點,同時刪去所有它發出的有向邊;

(3)依次迴圈以上兩步,直到:全部頂點已經輸出(排序結束),或被迫跳出迴圈(圖中存在環)

(注意理解程式碼中有個模仿棧結構的top“指標”和count入度陣列)

	void TopologicalSort()
	{
		int i,top=-1;
		for(i = 0;i<numVertexs;++i)
		{
			if(count[i] == 0)
			{
				count[i] = top;
				top = i;//top是用下標表示
			}
		}
		for(i = 0;i<numVertexs;++i)
		{


			if(top == -1)
				cout<<"Have a circle..."<<endl;
			else
			{
				int j = top;
				top = count[j];
				cout<<myv[j].data<<"-->";
				EdgeNode *l = myv[j].link;
				while(l)
				{
					int k = l->dest;
					if(--count[k] == 0)//這裡的--是將l所指出去相連的邊都刪掉。
					{
						count[k] = top;
						top = k;	
					}	
					l = l->next;
				}
			}
		}
	}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include"AllHead.h"
#define MAXSIZE 20
//單向圖。
class EdgeNode;

template<class T>
class GrapHVec;

template<class T>
class VertexList
{
	friend class GrapHVec<T>;
private:
	T data;
	EdgeNode *link;
public:
	VertexList():link(NULL)
	{}
	~VertexList(){}
};
class EdgeNode
{
public:
	int dest;
	EdgeNode *next;
public:
	EdgeNode()
	{
		next = NULL;
	}
	~EdgeNode(){}
};
template<class T>
class GrapHVec
{
private:
	VertexList<T> *myv;
	int maxSize;//最大
	int numVertexs;
	int numEdges;
	int *count;//建立一個入度陣列
public:
	GrapHVec(int sz=MAXSIZE)
	{
		maxSize = sz<=MAXSIZE?MAXSIZE:sz;
		myv = new VertexList<T>[maxSize];
		count = new int[maxSize];
		for(int i=0;i<maxSize;++i)
			count[i] = 0;
		numVertexs = 0;
		numEdges = 0;
	}
	~GrapHVec(){}
public:
	int GetNextNeighbor(T x1,T x2)
	{
		if(numVertexs == 0)
		{
			cout<<"空(GetFirstNeighbor)...";
			return ERROR;
		}
		int v1 = GetVerticespos(x1);
		int v2 = GetVerticespos(x2);
		EdgeNode *fp = myv[v1].link;
		while(fp!=NULL && (*fp).dest != v2)
			fp = (*fp).next;
		if(fp == NULL)
		{
			//cout<<"不存在有過連結.....";
			return -1;
		}
		fp = (*fp).next;
		if(fp != NULL)
			return (*fp).dest;
		else
		{
			//cout<<"沒有下一個結點....";
			return -1;
		}
	}
	int GetFirstNeighbor(T x)
	{
		if(numVertexs == 0)
		{
			cout<<"空(GetFirstNeighbor)...";
			return ERROR;
		}
		int v = GetVerticespos(x);
		EdgeNode *fp = myv[v].link;
		if(fp != NULL)
			return (*fp).dest;
		else
		{
			cout<<x<<" :沒有連結的結點....";
			return ERROR;
		}
	}
	int GetVerticespos(T x)
	{
		if(numVertexs == 0)
		{
			cout<<"空(Getpos)....";
			return FALSE;
		}
		int i;
		for(i=0;i<numVertexs;i++)
		{
			if(myv[i].data == x)
				return i;
		}
		return -1;
	}
public:
	int NumOfVertices(){return numVertexs;}
	int NumOfEdge(){return numEdges;}
	int InsertVertex(T x)
	{
		if(numVertexs >= maxSize)
		{
			cout<<"空間已滿不能插入...."<<endl;
			return ERROR;
		}
		myv[numVertexs++].data = x;
		return TRUE;
	}
	int InsertEdge(T x1,T x2)//A,B:A-->B
	{
		int v1 = GetVerticespos(x1);//A
		int v2 = GetVerticespos(x2);//B
		if(v1 == -1||v2 == -1)
		{
			cout<<"有一個節點不存在"<<endl;
			return ERROR;
		}
		EdgeNode *p1 = new EdgeNode;
		(*p1).dest = v2;
		(*p1).next = myv[v1].link;
		myv[v1].link = p1;
		count[v2]++;
		++numEdges;
	}
	void showVecGrap()
	{
		for(int i=0; i<numVertexs; ++i)
		{
			cout<<i<<":>"<<myv[i].data<<"-->";
			EdgeNode *e = myv[i].link;
			while(e != NULL)
			{
				cout<<e->dest<<"-->";
				e = e->next;
			}
			cout<<"Nul."<<endl;
		}
	}
public:
	void TopologicalSort()
	{
		int i,top=-1;
		for(i = 0;i<numVertexs;++i)
		{
			if(count[i] == 0)
			{
				count[i] = top;
				top = i;//top是用下標表示
			}
		}
		for(i = 0;i<numVertexs;++i)
		{


			if(top == -1)
				cout<<"Have a circle..."<<endl;
			else
			{
				int j = top;
				top = count[j];
				cout<<myv[j].data<<"-->";
				EdgeNode *l = myv[j].link;
				while(l)
				{
					int k = l->dest;
					if(--count[k] == 0)//這裡的--是將l所指出去相連的邊都刪掉。
					{
						count[k] = top;
						top = k;	
					}	
					l = l->next;
				}
			}
		}
	}
};
#include"graphvec.h"
int main()
{
	GrapHVec<char> tp;
	tp.InsertVertex('A');
	tp.InsertVertex('B');
	tp.InsertVertex('C');
	tp.InsertVertex('D');
	tp.InsertVertex('E');
	tp.InsertVertex('F');
	tp.InsertEdge('A','B');
	tp.InsertEdge('A','C');
	tp.InsertEdge('A','D');
	tp.InsertEdge('C','F');
	tp.InsertEdge('D','F');
	tp.InsertEdge('D','B');
	tp.InsertEdge('E','C');
	tp.InsertEdge('E','F');
	tp.showVecGrap();
	cout<<"========================="<<endl;
	tp.TopologicalSort();
	return 0;
}