数据结构-----图

图分为有向图和无向图。

图的存储:邻接矩阵,邻接表,链式前向星。

图的拓扑排序的前提:有向、无环

那么拓扑排序还可以判断一个有向图有没有环

力扣测试链接

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* findOrder(int numCourses, int** prerequisites, int prerequisitesSize, int* prerequisitesColSize, int* returnSize) {
    int* ans = (int*)malloc(sizeof(int) * 2001);//存放答案的数组
    int head[2000] = {0};//存放每个节点指向的边
    int to[4000] = {0};//存放每条边指向的节点
    int next[4000] = {0};//存放每条边指向的下一条边
    int d[2000] = {0};//入度数组
    int cnt = 1;//边的编号从1开始
    int len = 0;//答案数组的长度
    int q[4000];//队列
    int l = 0;//队列头
    int r = 0;//队列尾

    for (int i = 0; i < prerequisitesSize; i++) {//遍历边数组
        int from = prerequisites[i][1];//注意是先修了b才能修a,所以是b指向a
        int tp = prerequisites[i][0];//那么被指向的就是a

        d[tp]++;//被指向,那么它对应的度就加一
        next[cnt] = head[from];//新的边先指向老的边
        to[cnt] = tp;//新的边指向的节点赋值
        head[from] = cnt++;//新的边成为对应节点的头边
    }

    for (int i = 0; i < numCourses; i++) {//遍历度数组,找到度为0的点
        if (d[i] == 0)  {//如果点为0
            q[r++] = i;//把点放入队列
        }
    }

    while(l != r) {//队列不为空
        ans[len++] = q[l];//弹出队列头作为答案

        for (int j = head[q[l]]; j; j = next[j]) {//取出节点在链式前向星的头边,然后让它的邻居的入度都减一
            if (--d[to[j]] == 0) {//减一之后是0
                q[r++] = to[j];//把对应的节点放入队列
            }
        }
        l++;//队列头之前没有加一
    }

    if (len != numCourses) {//如果结果长度和正确的排序长度不相等,代表图有环不能拓扑排序
        *returnSize = 0;//返回空数组
        return NULL;
    }

    *returnSize = len;//返回的长度赋值
    
    return ans;//返回结果数组
}

 

posted @ 2024-01-22 22:43  lwj1239  阅读(24)  评论(0)    收藏  举报