目录
一、概述
宽度优先搜索、图以及节点的数据结构定义的表示可以看我的前一篇文章,宽度优先搜索轻松实现克隆图。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;
}
四、总结
宽度优先搜索虽然比较简单,但是可以解决一系列的问题,本文就使用宽度优先搜索实现了拓扑排序算法。这里主要是针对有向无环图进行的实现,有向有环图的实现等有时间在写篇博客。