天天看點

圖論 有向無環圖 拓撲排序 是什麼

一、有向無環圖

  • 有方向
  • 沒有閉環
圖論 有向無環圖 拓撲排序 是什麼

二、拓撲排序

拓撲排序是将有向無環圖的頂點排成一個線性序列的過程。

比如可将上圖

圖論 有向無環圖 拓撲排序 是什麼

三、拓撲排序步驟

1. 首先要任意選擇一個沒有前驅的頂點,即入度為0的點,然後将它輸出。

在下面這張圖中我們選擇1為出發點。

圖論 有向無環圖 拓撲排序 是什麼

2. 删除該節點以及與它相關聯的所有邊,這個點的nexts裡面的點入度就減少1

選擇1為出發點之後,我們将它輸出,并删除該節點以及與它相關聯的所有邊。

圖論 有向無環圖 拓撲排序 是什麼

3. 然後在删除後的圖中繼續找一個沒有前驅的節點,

這裡沒有前驅的節點隻有2和3.

這裡我們選擇3,那麼将節點3輸出後的圖 如下圖所示。

圖論 有向無環圖 拓撲排序 是什麼

4. 繼續找入度為0的點重複上述步驟。

接下來沒有前驅的節點隻有2和6了。

我們這裡選擇節點6,同樣的輸出節點6後删除。

然後繼續找沒有前驅的節點。這時候沒有前驅的節點隻剩下節點2.

圖論 有向無環圖 拓撲排序 是什麼

接下來的點繼續進行拓撲排序,

5. 得到的拓撲排序的一種如下圖所示。

圖論 有向無環圖 拓撲排序 是什麼

相信大家也都發現其實拓撲排序是不唯一的,我們選擇的出發點不同,結果就是不一樣的。

這裡給出大家針對上圖幾種拓撲排序序列。

圖論 有向無環圖 拓撲排序 是什麼

四、算法設計

用一個map儲存他的所有節點對應的入度。

用一個隊列儲存每次入度為0的節點然後pop,pop的順序就是拓撲排序的順序。

list <node*> tsort(graph G) {
	list<node*> res;
	unordered_map<node*, int> inmap; 
	queue<node*> zeronode;
	for (auto next : G.nodes) {//G.nodes是map
		inmap[next.second] = next.second->in;
		if (next.second->in == 0) {
			zeronode.push(next.second);
		}
	}
	while (!zeronode.empty()) {
		node* cur = zeronode.front();
		zeronode.pop();
		res.push_back(cur);
		for (auto next : cur->nexts) {
			inmap[next]--;
			if (inmap[next] == 0) {
				zeronode.push(next);
			}
		}
	}

	return res;
 }