目錄
一、概述
寬度優先搜索、圖以及節點的數據結構定義的表示可以看我的前一篇文章,寬度優先搜索輕鬆實現克隆圖。https://blog.csdn.net/kupepoem/article/details/106378672。理解了寬度優先搜索輕鬆實現克隆圖這篇文章就來看這篇文章就很easy了。
二、拓撲排序
對一個有向無環圖(Directed Acyclic Graph簡稱DAG)G進行拓撲排序,是將G中所有頂點排成一個線性序列,使得圖中任意一對頂點u和v,若邊<u,v>∈E(G),則u在線性序列中出現在v之前。通常,這樣的線性序列稱爲滿足拓撲次序(Topological Order)的序列,簡稱拓撲序列。簡單的說,由某個集合上的一個偏序得到該集合上的一個全序,這個操作稱之爲拓撲排序。
三、拓撲排序的實現
1、代碼實現
這個實現比較簡單,就是首先計算節點的入度,把入度爲0的點先挑選出來。然後進行寬度優先搜索,在搜索的過程中把入度爲0點的鄰居的入度減1。
vector<Node*> topSort(vector<Node*>& graph)
{
vector<Node*> result;
int s = graph.size();
unordered_map<Node*, int> m;
//初始化節點入度
for (int i = 0; i < graph.size(); i++)
{
m[graph[i]] = 0;
}
//計算節點入度
for (int i = 0; i < graph.size(); i++)
{
int ns = graph[i]->neighbors.size();
for (int j = 0; j < ns; ++j)
{
m[graph[i]->neighbors[j]] = m[graph[i]->neighbors[j]] + 1;
}
}
//把入度爲0的點 放入結果和隊列中
queue<Node*> queueNode;
for (int i = 0; i < graph.size(); i++)
{
if (m[graph[i]] == 0)
{
queueNode.push(graph[i]);
result.push_back(graph[i]);
}
}
//進行寬度優先搜索
while (!queueNode.empty())
{
Node *fnode=queueNode.front();
queueNode.pop();
int ns = fnode->neighbors.size();
for (int i = 0; i < ns; i++)
{
Node*nNode = fnode->neighbors[i];
m[nNode] = m[nNode] - 1;
if (m[nNode] == 0)
{
queueNode.push(nNode);
result.push_back(nNode);
}
}
}
return result;
}
2、代碼調用
調用也比較簡單,首先構建圖,然後直接調用topsort函數,結果爲1 3 2 4。
int main()
{
Node *node1 = new Node(1);
Node *node2 = new Node(2);
Node *node3 = new Node(3);
Node *node4 = new Node(4);
node1->neighbors.push_back(node2);
node3->neighbors.push_back(node2);
node2->neighbors.push_back(node4);
vector<Node*> graph;
graph.push_back(node1);
graph.push_back(node2);
graph.push_back(node3);
graph.push_back(node4);
auto result = topSort(graph);
return 0;
}
四、總結
寬度優先搜索雖然比較簡單,但是可以解決一系列的問題,本文就使用寬度優先搜索實現了拓撲排序算法。這裏主要是針對有向無環圖進行的實現,有向有環圖的實現等有時間在寫篇博客。