拓扑排序排序入门

文章介绍了拓扑排序的概念,它是对有向图的一种遍历方式,常用于解决课程预修关系的问题。通过DFS或BFS算法,结合访问状态数组和边的记录,可以判断是否存在环并生成排序序列。文中提供了两个示例,一个是完整的拓扑排序实现,另一个着重于环的检测,两者都强调了正确处理先修课程的重要性。
摘要由CSDN通过智能技术生成

拓扑排序

拓扑排序是一种基于有向图的遍历算法
因此对于简单题来说,就是对图的遍历加了顺序的要求,在使用dfs或bfs时稍加处理即可。

题目一

210. 课程表 II
思路
1.定义edges数组表示边
2.visited数组表示访问状态
3.要将节点的前导节点记录下来,表示有边相连。
3.进行遍历时,从每一个节点的出发,并visited[u]=1标记为访问中,不断往下遍历,直至为无先修课(称之为前导节点)将该节点入栈,回溯,期间若无未存储的前导节点时,该节点也该进栈了。若碰到的节点visited[]为1,为环,不可能存在拓扑排序。
代码

class Solution {
private:
vector<vector<int>>edges;//节点与节点的先后顺序以有向边进行存储
vector<int>visited;//表示节点的状态,搜索中,未搜索,已完成。
vector<int>result;
bool valid=true;
public:
    void dfs(int u)
    {
        visited[u]=1;
        for(int v:edges[u])
        {
            if(visited[v]==0)
            {
                dfs(v);
                if(!valid)
                {
                    return ;
                }
            }
            else if(visited[v]==1)
            {
                valid=false;
                return ;
            }
        }
        visited[u]=2;
        result.push_back(u);
    }
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        visited.resize(numCourses);
        for(const auto& info:prerequisites)
        {
            edges[info[1]].push_back(info[0]);//将其前导节点存入其数组中,之后要对它们进行遍历并先入栈。
        }
        for(int i=0;i<numCourses&&valid;++i) 对每个节点的前导节点进行遍历。
        {
            if(!visited[i])
            {
                dfs(i);
            }
        } 
        if(!valid) 如果有环,不存在拓扑排序。
        {
            return{};
        }
        reverse(result.begin(),result.end());栈顶到栈尾就是该排序序列,但需将其首尾转置
        return result;
    }
};

原始题

链接
题目要求相同,上一题是该题的进阶版,但其实思路是一样的。

class Solution {
private:
    vector<vector<int>>edges;
    vector<int>visited;
    bool valid=true;
public:
    void dfs(int u)
    {
        visited[u]=1;
        for(int v:edges[u])
        {
            if(visited[v]==0)
            {
                dfs(v);
                if(!valid)
                {
                    return ;
                }
            }
            else if(visited[v]==1)
            {
                valid=false;
                return ;
            }
        }
        visited[u]=2;
    }
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        edges.resize(numCourses);
        visited.resize(numCourses);
        for(auto info:prerequisites)
        {
            edges[info[1]].push_back(info[0]);
        }
        for(int i=0;i<numCourses&&valid;++i)
        {
            if(!visited[i])
            {
                dfs(i);
            }
        }
        return valid;
    }
};

上一题更好的体现了(以栈的先进后出)进行拓扑排序的方法,以此得出正确的顺序。
而原始题更多的是考察若出现环便不能进行拓扑排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值