拓扑排序解题-DFS解决

拓扑排序

什么是拓扑排序

它是一个有向无环图的所有顶点的线性序列,也就是说,如果有向图中存在环,那么它就没有拓扑排序。除此之外,这个线性序列的特点有:

  • 若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面
  • 每个顶点只出现一次

DFS求解拓扑排序

下面是使用深度优先搜索(DFS)求解一个图的拓扑排序
以一个例题为例子:leetcode-207
这里我们将每一个课程看成是一个节点,每个节点有三种状态

  • 已经搜索过的节点,设置为2
  • 正在搜索的节点,设置为1,如果搜索过程中又碰到节点是这个状态,说明这个图中存在环,比如遍历顺序如下:1->2->3->1,因为1的状态之前已经是1了,下次再搜索到它就说明存在环了
  • 还没有搜索的节点,设置为0

具体思路如下:

1.首先将有向图构造好,我们这里用的是一个数组(bian)来存放当前节点的相邻节点
2.遍历每一个节点,对每一个节点,判断它是否已经被搜索过,没有被搜索过则遍历该节点的相邻节点,对相邻节点的状态进行判断,具体如下:

  • 如果相邻节点没有被搜索过,则将其状态设置为1,说明这个节点还在搜索当中,然后继续往下搜索,寻找该节点的相邻节点
  • 如果相邻节点的状态为1,说明之前它已经被搜索过了,出现了环,则直接退出
  • 相邻节点都遍历完后将当前节点的状态设置为2,说明已经搜索过了

代码如下:

class Solution {
    List<List<Integer>> bian;
    int vis[];
    boolean res = true;
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        //利用拓扑排序算法
        //先构造一个有向图
        bian = new ArrayList<List<Integer>>();
        for(int i=0;i<numCourses;i++){
            bian.add(new ArrayList<Integer>());
        }
        //加入边,即构造有向图
        int n=prerequisites.length;
        for(int i=0;i<n;i++){
            int mid[]=prerequisites[i];
            bian.get(mid[1]).add(mid[0]);//说明mid[1]课程完成后才能是mid[0]
        }
        vis = new int[numCourses];//初始化都是0,表明都没有搜索过
        //变量每一个顶点,即课程
        for(int i=0;i<numCourses;i++){
            if(vis[i]==0){
                dfs(i);//以该顶点为开始,进行深度优先遍历
            }
        }
        return res;
    }
    public void dfs(int dot){
        //遍历该顶点相邻的下一个点
        List<Integer> mid=bian.get(dot);
        int l=mid.size();
        if(!res){//说明已经是有环了,退出循环
            return;
        }
        for(int i=0;i<l;i++){
            //判断是否遍历过
            int tmp=mid.get(i);
            if(vis[tmp]==0){
                vis[tmp]=1;//说明这个点正在搜索中
                dfs(tmp);//继续搜索
                if(!res){//说明已经是有环了,退出循环
                    return;
                }
            }
            else if(vis[tmp]==1){
                res=false;//说明有环存在了
                return;
            }
        }
        vis[dot]=2;//表示这个已经搜索完了
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lzl2040

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值