拓扑排序是一种针对有向无环图(DAG)的线性排序算法,用于确定图中各个顶点的一种顺序,使得对于任何一条有向边(src,dest),顶点src在排序中出现在顶点dest之前。在本篇博文中,我们将深入了解拓扑排序的原理、代码实现以及一些应用场景。
一、拓扑排序原理
拓扑排序的主要思想是通过寻找入度为0的顶点,逐步移除这些顶点并更新相关顶点的入度,从而实现图中顶点的线性排序。在拓扑排序中,入度表示有多少条边指向一个顶点。
二、拓扑排序步骤
- 计算每个顶点的入度。
- 将入度为0的顶点放入队列。
- 从队列中弹出一个顶点,并将其放入排序结果中。
- 对该顶点的所有邻接顶点,将其入度减1。
- 若邻接顶点的入度变为0,则将其放入队列。
- 重复步骤3~5,直到队列为空。
三、拓扑排序代码实现
下面是代码所创建的图
拓扑排序结果:0 2 1 3 4
以下是使用C++实现拓扑排序的示例代码:
#include<iostream>
#include<queue>
using namespace std;
#define MaxSize 100 //图中最多顶点数
int result[MaxSize]; //存放拓扑排序的结果
struct Edge { //边结点
int vex;
Edge* next;
};
struct Vex { //顶点结点
int data;
Edge* firstEdge;
};
struct Graph { //图的邻接表存储
Vex vexList[MaxSize];
int inDegree[MaxSize];//存放各顶点的入度
int vex_num, edge_num;
};
//初始化图
void initGraph(Graph& graph, int vex_num) {
graph.edge_num = 0;
graph.vex_num = vex_num;
for (int i = 0; i < vex_num; i++) {
graph.vexList[i].data = i;
graph.vexList[i].firstEdge = NULL;
graph.inDegree[i] = 0;
}
}
//添加边
void addEdge(Graph& graph, int src, int dest) {
Edge* newEdge = (Edge*)malloc(sizeof(Edge));
newEdge->vex = dest;
newEdge->next = graph.vexList[src].firstEdge;
graph.vexList[src].firstEdge = newEdge;
graph.inDegree[dest]++;
graph.edge_num++;
}
//拓扑排序
bool TopologicalSort(Graph graph) {
queue<int> q; //存储入度为0的顶点
for (int i = 0; i < graph.vex_num; i++) {
if (graph.inDegree[i] == 0) { //入度为0
q.push(i); //将所有入度为0的顶点 进队
}
}
int count = 0; //计数 记录当前已经输出的顶点数
while (!q.empty()) { //队非空 则存在入度为0的顶点
int front = q.front(); //队头顶点
result[count++] = front;
q.pop(); //出队
//将front这个顶点的所有邻接顶点的入度减1 此时若入度为0则入队
for (Edge* p = graph.vexList[front].firstEdge; p != NULL; p = p->next) {
int v = p->vex;
graph.inDegree[v]--;
if (graph.inDegree[v] == 0) {
q.push(v);
}
}
}
//若有回路则总有几个顶点的入度永远都不为0 那么就不会入队 count就小于顶点个数
if (count < graph.vex_num) {
return false; //排序失败 有向图中有回路
}
else {
return true; //拓扑排序成功
}
}
int main() {
Graph graph;
initGraph(graph, 5);
addEdge(graph, 0, 1);
addEdge(graph, 1, 3);
addEdge(graph, 2, 3);
addEdge(graph, 2, 4);
addEdge(graph, 3, 4);
if (TopologicalSort(graph)) {
cout << "拓扑排序成功:" << endl;
for (int i = 0; i < graph.vex_num; i++) {
cout << result[i] << " ";
}
cout << endl;
}
else {
cout << "拓扑排序失败,有向图中有回路" << endl;
}
return 0;
}
四、运行结果
结果正确!!!!!!!!