Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 463|回复: 0

[算法学习]拓扑排序初步练习

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-12-4 00:07:53 | 显示全部楼层 |阅读模式
    拓扑排序简单来说就是把一个图的所有节点排序,使得每一条有向边(u,v)对应的u都排在v的前面。 拓扑排序最大的用途就是判断一个有向图是否有环。

    无前趋的顶点优先的拓扑排序方法

         该方法的每一步总是输出当前无前趋(即人度为零)的顶点,其抽象算法可描述为:
         NonPreFirstTopSort(G){//优先输出无前趋的顶点
           while(图G中有人度为0的顶点)do{
            从G中选择一个人度为0的顶点v且输出之;
            从G中删去v及其所有出边;
            }
           if(输出的顶点数目<|V(G)|)
             //若此条件不成立,则表示所有顶点均已输出,排序成功。
             Error("G中存在有向环,排序失败!");
          }
       
      
       
       

         
       

         
       
      



       

    性质

    1、 拓扑排序在有向无环图中才能排出有效的序列,否则能判断该有向图有环。

    2、如果输入的有向图中的点,不存在入度为0的点,则该有向图存在回路

    3、如果存在的入度为0的点大于一个,则该有向图肯定不存在一个可以确定的拓扑序列但并不妨碍拓扑排序



    例: 有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。





    Input

    输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。

    接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。





    Output

    给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。



    其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;

    输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。





    Sample Input

    4 3

    1 2

    2 3

    4 3



    Sample Output

    1 2 4 3



    典型的拓扑排序算法


    import java.util.*;
    方法一:(邻接矩阵实现图存储)
    public class Main {
            private  int n, m;
            private int[] indegree;// 顶点的入度
            private int[] result;// 保存最后排好序的结果
            private int[][] G;// 邻接矩阵存储
            private  Queue<Integer> que;//存入入度为0的顶点
            public Main(int n,int m,int[] indegree,int[][] G){
                 this.n=n;
                 this.m=m;
                 this.indegree=indegree;
                 this.G=G;
            }
                
          
            public static void main(String[] args) {
              Scanner sc = new Scanner(System.in);
               int[][] G;
               int[] indegree;
               int n,m;
                while (sc.hasNext()) {
                  n = sc.nextInt();
                  m = sc.nextInt();
                  G = new int[n + 1][n + 1];
                  indegree = new int[n + 1];
                     while (m-- > 0) {
                       int u = sc.nextInt();
                       int v = sc.nextInt();
                  if (G[v] == 0) {// 这个条件一定要,避免重边的情况比如a b可能出现两次的情况
                         indegree[v]++;
                         G[v] = 1;
                        }
                     }
                     Main ma=new Main(n,m,indegree,G);
                            ma.topsort();
                           
                    }
            }
            private  void topsort() {
              result = new int[n + 1];
              que = new PriorityQueue<Integer>();//同名次时,序号小的排前,所以用优先队列
              int index = 0;
              for (int i = 1; i <= n; i++) {//找出图中所有入度为O的顶点
                if (indegree == 0)
                    que.add(i);//编号小的在前
              }
              while (!que.isEmpty()) {
                 int u = que.poll();
                 result[++index] = u;
                 for (int i = 1; i <= n; i++) {
                    if (G == 1) {
                      indegree--;//模拟删除顶点,i的入度减1
                      if (indegree == 0)
                        que.add(i);
                    }
                 }
              }
              // 输出
               System.out.print(result[1]);
               for (int i = 2; i <= n; i++) {
                    System.out.print(" "+result);
               }
               System.out.println();
            }
      }
    import java.util.*;
    方法二:拓扑排序(使用邻接表实现)
    public class Main{
            private int n, m;
            private int[] indegree;// 顶点的入度
            private int[] result;// 保存最后排好序的结果
            private List<ArrayList<Integer>> G;// 邻接表。
            private Queue<Integer> que;
            public Main(int n,int m,int[] indegree,List<ArrayList<Integer>> G){
                 this.n=n;
                 this.m=m;
                 this.indegree=indegree;
                 this.G=G;
            }
            public static void main(String[] args) {
              int n,m;
              int[] indegree;
              List<ArrayList<Integer>> G;
              Scanner sc = new Scanner(System.in);
              while (sc.hasNext()) {
                n = sc.nextInt();
                m = sc.nextInt();
                G = new ArrayList<ArrayList<Integer>>();
                for(int i = 1;i<=n+1;i++)
                   G.add(new ArrayList<Integer>());//初始化邻接表
                indegree = new int[n + 1];
                while (m-- > 0) {
                  int u = sc.nextInt();
                  int v = sc.nextInt();
            if (!G.get(u).contains(v)) {// 这个条件一定要,避免重边的情况比如a b可能出现两次的情况
                     indegree[v]++;
                     G.get(u).add(v);
                   }
                }
                 Main ma=new Main(n,m,indegree,G);
                 ma.topsort();
               }
            }
                           
           
            private  void topsort() {
              result = new int[n + 1];
              que = new PriorityQueue<Integer>();
              int index = 0;
              for (int i = 1; i <= n; i++) {
                 if (indegree == 0)
                    que.add(i);
               }
               while (!que.isEmpty()) {
                 int v = que.poll();
                 result[++index] = v;
                 for (int i : G.get(v)) {
                     indegree--;
                     if (indegree == 0)
                       que.add(i);
                 }
               }
              // 输出
             System.out.print(result[1]);
             for (int i = 2; i <= n; i++) {
                System.out.print(" " + result);
             }
             System.out.println();
           }
    }
    [/code]





      
      
       
       

         
       

         
       
      
    复制代码

    源码下载:http://file.javaxxz.com/2014/12/4/000753250.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 04:11 , Processed in 0.370148 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表