圖的應用之拓撲排序實現(輔助棧)

何爲拓撲排序:

一般常見的圖是有環的,不需要考慮頂點的先後順序,而比如在一些工程中,工程的流程圖就需要考慮頂點的先後順序,比如B的前置條件是完成A,這就需要拓撲排序來判斷圖是否滿足拓撲次序,並且能夠形象的顯示各個頂點的先後順序。

拓撲排序有多種解,拓撲排序的解並不是唯一的,有些頂點的優先性是相同的。

通常我們把頂點表示活動,邊表示活動的先後關係的有向圖稱爲頂點活動網(Activity On Vertex Network),即AOV網。

拓撲排序的算法思路:

有向圖的每個頂點有不同的入度,不斷把入度爲0的頂點的去除,並去除與之相連的邊,把其相連頂點的入度減小1,不斷循環。

最終判斷是否輸出的頂點數小於原圖的頂點數,小於則不滿足拓撲次序,否則滿足拓撲次序,輸出的頂點爲一種拓撲序列。

拓撲排序所需的圖的鄰接表結構:

爲了方便去除入度爲0的頂點和邊,所以使用帶入度的圖的鄰接結構,圖的鄰接表結構如下:

#define MAXVERTEX 10       //最大頂點數,默認爲10
struct EdgeNode          //邊表
{
	int adjvertex;       //鄰接點的下標
	int weight;          //權值
	EdgeNode *next;     //指針指向下一個鄰接點
};

typedef struct VertexNode      //頂點表
{
	int data;            //頂點信息
	int in;               //頂點入度
	EdgeNode *firstEdge;       //邊表指針,指向邊表
}AdjList[MAXVERTEX];

typedef struct GraphAdjList
{
	AdjList adjList;
	int vertexesNum;        //頂點數
	int edgesNum;           //邊數
}*GraphAdjList;

拓撲排序實現:

輔助建立了一個棧來輸出入度爲0的頂點

//拓撲排序
bool TopologicalSort(GraphAdjList GAL)
{
	int i;//用於循環
	int count;            //存儲要輸出的頂點個數
	EdgeNode *e;
	int k;    
	//初始化用於輔助的棧
	stack<int> stack;     //棧用於存放入度爲0的頂點
	int topNum = 0;            //存儲取出的棧頂數
	//將入度爲0的頂點放入棧
	for (i = 0; i < GAL->vertexesNum; i++)
	{
		if (GAL->adjList[i].in == 0)
		{
			stack.push(i);
		}
	}
	while (stack.empty() != true)     //如果存在入度爲0的頂點,不斷循環
	{
		topNum = stack.top();  //topNum賦值爲棧頂指針
		stack.pop();       //棧頂出棧
		count++;          //輸出個數自增1
		cout << GAL->adjList[topNum].data << endl;  //輸出頂點
		//遍歷該頂點的鄰接表
		for (e = GAL->adjList[topNum].firstEdge; e; e = e->next)
		{
			k = e->adjvertex;
			if ((--GAL->adjList[k].in) == 0) //鄰接點自減1,並判斷是否爲0
			{
				stack.push(k);
			}
		}
	}
	//循環結束,判斷是否是拓撲次序
	if (count<GAL->vertexesNum)
	{
		return false;
	}
	else
	{
		return true;
	}
}

拓撲排序時間複雜度:

初始遍歷入度爲0的頂點複雜度爲O(n),後來循環中入棧出棧,複雜度爲O(e),總的時間複雜度O(n+e)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章