记录算法使用场景和代码实现
算法简介
拓扑排序算法是将有向图看成一条序列。
使用场景
我所知的两种场景如下:
- 拓扑排序判环
- 打印一种拓扑排序序列
代码实现
拓扑排序判环
步骤:
- 建图:每个节点记录入度属性
- 找到入度为0的所有结点,入栈
- 出栈结点,删除该结点------该结点指向的结点入度减一,如果入度为0,入栈
- 如果所有结点都删掉,没有环,否则有环
c
typedef struct Graph {
int **graph;
int *in;
int *graphColSize;
} Graph;
Graph CreateGraph(int n, int **prerequisites, int prerequisitesSize) {
Graph G;
int **graph = (int **)malloc(sizeof(int *)*(n));
int *graphColSize = (int *)malloc(sizeof(int)*(n));
int *in = (int *)malloc(sizeof(int)*(n));
memset(graph, 0, sizeof(int *)*(n));
memset(graphColSize, 0, sizeof(int)*(n));
memset(in, 0, sizeof(int)*(n));
for(int i=0; i<prerequisitesSize; i++) {
int a = prerequisites[i][0];
int b = prerequisites[i][1];
// printf("%d %d\n", a, b);
if(graph[b] == NULL) {
graph[b] = (int *)malloc(sizeof(int)*n);
}
graph[b][graphColSize[b]++] = a;
in[a]++;
}
G.graph = graph;
G.graphColSize = graphColSize;
G.in = in;
return G;
}
bool IsHasCircle(Graph *graph, int graphSize) {
int stack[2000];
int topPos = 0;
int zeroInNodeNum = graphSize;
for(int i=0; i<graphSize; i++) {
if(graph->in[i] == 0) {
stack[topPos++] = i;
}
}
if(topPos == 0) return false;
while (topPos > 0) {
int top = stack[--topPos];
zeroInNodeNum--;
for(int i=0; i<graph->graphColSize[top]; i++) {
int neighborId = graph->graph[top][i];
(graph->in[neighborId])--;
if(graph->in[neighborId] == 0) {
stack[topPos++] = neighborId;
}
}
}
return zeroInNodeNum == 0;
}
打印一种拓扑排序序列
算法过程不多作介绍,只是在删除结点时,记录结果。
c
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* findOrder(int numCourses, int** prerequisites, int prerequisitesSize, int* prerequisitesColSize, int* returnSize) {
Graph graph = CreateGraph(numCourses, prerequisites, prerequisitesSize);
int *res = (int *)malloc(sizeof(int)*numCourses);
int cnt = 0;
int stack[2000];
int topPos = 0;
int zeroInNodeNum = numCourses;
for(int i=0; i<numCourses; i++) {
if(graph.in[i] == 0) {
stack[topPos++] = i;
}
}
while (topPos > 0) {
int top = stack[--topPos];
res[cnt++] = top;
zeroInNodeNum--;
for(int i=0; i<graph.graphColSize[top]; i++) {
int neighborId = graph.graph[top][i];
(graph.in[neighborId])--;
if(graph.in[neighborId] == 0) {
stack[topPos++] = neighborId;
}
}
}
if(zeroInNodeNum != 0) *returnSize = 0;
else *returnSize = cnt;
return res;
}