算法-拓扑排序-C

记录算法使用场景和代码实现

算法简介

拓扑排序算法是将有向图看成一条序列。

使用场景

我所知的两种场景如下:

  • 拓扑排序判环
  • 打印一种拓扑排序序列

代码实现

拓扑排序判环

步骤:

  1. 建图:每个节点记录入度属性
  2. 找到入度为0的所有结点,入栈
  3. 出栈结点,删除该结点------该结点指向的结点入度减一,如果入度为0,入栈
  4. 如果所有结点都删掉,没有环,否则有环
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;
}

leetcode-207. 课程表

打印一种拓扑排序序列

算法过程不多作介绍,只是在删除结点时,记录结果。

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;
}

leetcode-210. 课程表||

相关推荐
名字还没想好☜7 小时前
Python f-string 进阶:数字格式化、对齐填充、调试 = 号与嵌套表达式
开发语言·数据库·python·字符串格式化·f-string
.道阻且长.7 小时前
2.LeetCode算法习题讲解--双指针--复写零
算法·leetcode·职场和发展
To_OC9 小时前
LC 438 找到所有字母异位词:暴力超时后,我靠滑动窗口一招搞定
javascript·算法·leetcode
一壶浊酒..11 小时前
Scrape Webpack练习
开发语言·javascript·webpack
命运之光11 小时前
【C语言完整代码】就诊信息管理系统
java·c语言·开发语言
命运之光11 小时前
【C语言完整代码】图书管理系统:图书馆场景下的增删改查实战
c语言·开发语言
猿长大人12 小时前
C# | Serilog 新手入门
开发语言·c#·.net·log
Forever Nore12 小时前
学完C语言力扣第一题做不来正常吗
数据结构·算法
hansang_IR12 小时前
【题解】LC:倍增 / 区间并查集(Range Parallel Unionfind)
c++·算法·并查集