拓扑排序是一种对有向无环图(DAG)进行排序的算法。它将图中的节点按照依赖关系进行排序,使得所有的依赖关系都得到满足。
以下是拓扑排序的基本步骤:
- 创建一个队列(可以使用数组或队列数据结构),用于存储入度为 0 的节点。
- 初始化一个入度数组,用于记录每个节点的入度。
- 遍历图中的所有节点,统计每个节点的入度。入度表示有多少个节点指向该节点。
- 将入度为 0 的节点加入队列中。
- 循环执行以下步骤直到队列为空:
- 从队列中取出一个节点,并将其加入排序结果中。
- 遍历该节点的所有邻居节点,将其入度减 1。
- 如果邻居节点的入度减为 0,则将其加入队列中。
- 如果排序结果中的节点数量等于图中的节点数量,则表示拓扑排序成功;否则,表示图中存在环,无法进行拓扑排序。
拓扑排序可以应用于诸如任务调度、编译顺序、依赖关系分析等场景。
注意:拓扑排序要求图是有向无环图(DAG),如果图中存在环,则无法进行拓扑排序。
下面是使用javascript,python和c++实现的方式:
function topologicalSort(numVertices, edges) {
const graph = {}; // 邻接表
const indegree = new Array(numVertices + 1).fill(0); // 入度数组
// 初始化邻接表和入度数组
for (let i = 1; i <= numVertices; i++) {
graph[i] = [];
}
// 构建邻接表和入度数组
for (const [u, v] of edges) {
graph[u].push(v);
indegree[v]++;
}
const result = [];
const queue = [];
// 将入度为 0 的节点加入队列
for (let i = 1; i <= numVertices; i++) {
if (indegree[i] === 0) {
queue.push(i);
}
}
// 拓扑排序
while (queue.length > 0) {
const node = queue.shift();
result.push(node);
// 更新邻居节点的入度
for (const neighbor of graph[node]) {
indegree[neighbor]--;
// 若邻居节点入度为 0,则加入队列
if (indegree[neighbor] === 0) {
queue.push(neighbor);
}
}
}
return result;
}
示例用法:
const input = [
[6, 8],
[1, 2],
[1, 3],
[2, 4],
[2, 5],
[3, 4],
[3, 6],
[4, 6],
[5, 6]
];
const numVertices = input[0][0];
const edges = input.slice(1).map(([u, v]) => [parseInt(u), parseInt(v)]);
const sorted = topologicalSort(numVertices, edges);
console.log(sorted); // 输出: [1, 2, 3, 5, 4, 6]
在这个例子中,输入包括点的个数和边的条数,以及每条边连接的两个点的信息。使用 topologicalSort
函数对输入进行拓扑排序,并将结果打印到控制台上。
请注意,上述实现假设输入的图是有向无环图(DAG),否则结果可能不正确。
from collections import defaultdict
def topologicalSort(numVertices, edges):
graph = defaultdict(list)
indegree = [0] * (numVertices + 1)
# Build the graph and calculate the indegree of each vertex
for u, v in edges:
graph[u].append(v)
indegree[v] += 1
result = []
queue = []
# Enqueue vertices with indegree 0
for i in range(1, numVertices + 1):
if indegree[i] == 0:
queue.append(i)
# Perform topological sort
while queue:
node = queue.pop(0)
result.append(node)
# Update the indegree of neighboring vertices
for neighbor in graph[node]:
indegree[neighbor] -= 1
# Enqueue vertices with indegree 0
if indegree[neighbor] == 0:
queue.append(neighbor)
return result
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<int> topologicalSort(int numVertices, vector<pair<int, int>>& edges) {
vector<vector<int>> graph(numVertices + 1);
vector<int> indegree(numVertices + 1, 0);
// Build the graph and calculate the indegree of each vertex
for (auto& edge : edges) {
int u = edge.first;
int v = edge.second;
graph[u].push_back(v);
indegree[v]++;
}
vector<int> result;
queue<int> q;
// Enqueue vertices with indegree 0
for (int i = 1; i <= numVertices; i++) {
if (indegree[i] == 0) {
q.push(i);
}
}
// Perform topological sort
while (!q.empty()) {
int node = q.front();
q.pop();
result.push_back(node);
// Update the indegree of neighboring vertices
for (int neighbor : graph[node]) {
indegree[neighbor]--;
// Enqueue vertices with indegree 0
if (indegree[neighbor] == 0) {
q.push(neighbor);
}
}
}
return result;
}