zoukankan      html  css  js  c++  java
  • 实验九报告

    20182319 2019-2020-1 《数据结构与面向对象程序设计》实验九报告


    课程:《程序设计与数据结构》
    班级: 1823
    姓名: 彭淼迪
    学号:20182319
    实验教师:王志强
    实验日期:2019年12月7日
    必修/选修: 必修

    1.实验内容

    • (1) 初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图需要自己定义(顶点个数、边个数,建议先在草稿纸上画出图,然后再输入顶点和边数)(2分)

    • (2) 图的遍历:完成有向图和无向图的遍历(深度和广度优先遍历)(4分)

    • (3) 完成有向图的拓扑排序,并输出拓扑排序序列或者输出该图存在环(3分)

    • (4) 完成无向图的最小生成树(Prim算法或Kruscal算法均可),并输出(3分)

    • (5) 完成有向图的单源最短路径求解(迪杰斯特拉算法)(3分)

    2. 实验过程及结果

      其实大部分都已经写过了,对于这部分我们已经实现过的,我们只需要把它一下就好了,所以我们这一次的任务在某一部分会比较轻松,当然,也是只有某一部分。还是有一部分比较难的,比如说我们的最小生成树的算法,虽然以前用手算过,但毕竟是人用全局的想法在做,落实到代码上可就没有那么简单了。

    • 首先,是找出我们已经做过的部分,java的一大优势就在于它的调用使一段代码的利用率高,可以被我们多次利用,我们自然也不能放过这个机会。我们可以发现我们是已经实现过(1)(2)(3)(5),但是我们要怎么用它们呢?有一个办法是直接继承,另一个方法是在我们这个新方法里开原来的类,因为继承是一种比较官方的方法,很多人都会这么用,所以我选择了开新的类。其中那个Boolean型表示的是它是有向还是无向的。ph表示的是原来的图,tuo表示的是原来拓扑排序。可以看到我在后面是直接用了它们的东西的。
    private photo1 ph=new photo1();
        private tuopu tuo=new tuopu();
        private boolean f;
        public photo2(boolean f){
                this.f=f;
        }
        public void insertpoint(int a){
            ph.insertpoint(a);
            tuo.insertpoint(a);
        }
        public void deletepoint(int a){
            ph.deletepoint(a);
            tuo.deletepoint(a);
        }
        public void insertline(int a,int b,int c){
            ph.insertline(a,b,c);
            tuo.insertline(a,b,c);
            if(f){
                ph.insertline(b,a,c);
                tuo.insertline(b,a,c);
            }
        }
        public void insertline(int a,int b){
            ph.insertline(a,b);
            tuo.insertline(a,b);
            if(f){
                ph.insertline(b,a);
                tuo.insertline(b,a);
            }
        }
    
    • 然后,我们需要实现的就只有一个最小生成树了,我们可以直接把它加在我们这个新类里,但是我们这个新类的局限性还是挺大的,毕竟它牵扯到的东西太多了,所以我的想法是把这个方法分给两个原型,因为拓扑里不太用得着,而且这个方法要用到许多图里的参数,所以我是分配给了图。
    • 按照老师上课说过的方法,我们可以使用prim或Kruscal,在这里,我选用的是prim算法,就是每次都从已有的点有找距离这些点中任意一点最近的一个点,然后把这加入到已有点列。依次往复,直到结束。
     public int[][] smallest(){
            int[][] result=new int[200][2];
            int[] dp1=new int[200],dp2=new int[200];
            int min=0;
            for(int i=0;i<200;i++){
                if(p1[i]){min=i;break;}
            }
            for(int i=0;i<200;i++){
                dp1[i]=999999;
                dp2[i]=999999;
                result[i][0]=999999;
                result[i][1]=999999;
            }
            dp1[min]=0;
            result[min][1]=min;
            result[min][0]=0;
            int count1=1;
            while(count1!=count){
                int a=199,b=999999,c=999999;
                for(int i=0;i<200;i++){
                    if(panduan1(i,dp1)){
                        for(int j=0;j<200;j++){
                            if(!panduan1(j,dp1)){
                                for(int k=0;k<200;k++){
                                    if(panduan1(k,dp1)&&tu[k][j]!=0&&tu[k][j]<c){
                                        a=j;
                                        b=k;
                                        c=tu[k][j];
                                    }
                                }
                            }
                        }
                    }
                }
                dp1[a]=c;
                result[a][0]=c;
                result[a][1]=b;
                count1++;
            }
            return result;
        }
    
    • 中间那一段阶梯状的确有点长,不太好看,不过它却是我们刚刚说到的那个方法实现所在。然后也是一沿用了我一贯的风格,把999999当无穷大。
    • 当然,这么好玩的程序自然也不能少了一点人性化的输入输出是不是,于是出于人性化的考虑,我也特地为客户增加了许多可以选择的方向,让他们可以自己选择进行什么操作,什么时候停止。让人用得舒适放心。
    System.out.println("请问你是想要输入有向图还是无向图?(输入1为无向图,输入2为有向图)");
                int n=scan.nextInt();
                photo2 ph =new photo2(n==1);
                System.out.println("你想输入几个点?");
                int t=scan.nextInt();
                System.out.println("你可以开始输入了:");
                for(int i=0;i<t;i++){
                    int pmd=scan.nextInt();
                    ph.insertpoint(pmd);
                }
                System.out.println("你想输入几条边呢?");
                t=scan.nextInt();
                System.out.println("它是有权的吗?(输入1为无权图,输入2为有权图)");
                int pmd0=scan.nextInt();
                System.out.println("你可以输入了:");
                if(pmd0==1){
                    System.out.println("输入的格式为“出点 入点”");
                    for(int i=0;i<t;i++){
                        int pmd1=scan.nextInt(),pmd2=scan.nextInt();
                        ph.insertline(pmd1,pmd2);
                    }
                }
                else{
                    System.out.println("输入的格式为“出点 入点 权”");
                    for(int i=0;i<t;i++){
                        int pmd1=scan.nextInt(),pmd2=scan.nextInt(),pmd3=scan.nextInt();
                        ph.insertline(pmd1,pmd2,pmd3);
                    }
                }
                int x;
                do{
                    System.out.println("请输入你想进行的操作:
    1.表示广度优先遍历
    2.表示深度优先遍历
    3.表示拓扑排序
    4.表示生成最小生成树
    5.表示求两点最近距离
    6.不要这个图了");
                    x=scan.nextInt();
                    switch(x){
                        case 1:
                            ph.bfs();
                            break;
                        case 2:
                            ph.dfs();
                            break;
                        case 3:
                            System.out.println(ph.tuopu());
                            break;
                        case 4:
                            int pmd[][]=ph.smallest();
                            System.out.print("         陈列点:");
                            for(int j=0;j<200;j++){
                                if(pmd[j][0]!=999999) System.out.printf("%8d  ",j);
                            }
                            System.out.println("");
                            System.out.print("       上一个点:");
                            for(int j=0;j<200;j++){
                                if(pmd[j][0]!=999999) System.out.printf("%8d  ",pmd[j][1]);
                            }
                            System.out.println("");
                            System.out.print("与上一个点的距离:");
                            for(int j=0;j<200;j++){
                                if(pmd[j][0]!=999999) System.out.printf("%8d  ",pmd[j][0]);
                            }
                            System.out.println("");
                            break;
                        case 5:
                            int pmd1=scan.nextInt(),pmd2=scan.nextInt();
                            System.out.println(ph.shorest(pmd1,pmd2));
                            break;
                    }
                }while(x!=6);
    
    

    运行结果

    在这里插入图片描述

    3. 实验过程中遇到的问题和解决过程

    • 问题1:除了(4)我们都是可以用原来的东西,但我们需要新加入一个最小生成树的方法,我们应该怎么办呢?
    • 问题1解决方案:在前面的介绍中,我们已经提到过我们可以使用继承和引用的方法,但其实我们还没有考虑到这个新方法我们应该怎么把它融入进去,我觉得有三个方法:一、直接加在我们的新类里,让它成为新类的一部分,这个方法确实可以满足眼下的要求,但仅此而已;二、我们可以开一个专门的类,我们用这个专门的类来实现,这个方法有两点不妥,其一,为了一个单独的功能就开一个新的类,这无疑会加重以后我们使用时的负担,本来新建一个类是为了方便,结果反而会更不方便,那要它有什么用。其二,最小生成树有许多都要依靠我们的图,我们新建的这个类最后还是要依靠我们的图。所以我选择了方法三:我们把这个方法加在我们的图的类里,因为我们本来就要调用图,我们也没有增加多少事,反而让我们的图这个类更加完善,而且我们也不用另外再开一个图来制造麻烦,可谓一举两得。
  • 相关阅读:
    img标签与span一起使用不在同一条线上
    媒体查询
    section标签实现文字滚动
    js活jQuery实现动态添加、移除css/js文件
    页面中动态改变浏览器标题
    css清浮动与动态计算元素宽度
    js实现60s倒计时效果
    js与es6中获取时间戳
    JavaScript中实现小数点后保留2位
    GMT时间转换
  • 原文地址:https://www.cnblogs.com/ydfy/p/12007990.html
Copyright © 2011-2022 走看看