zoukankan      html  css  js  c++  java
  • 20182326 2019-2020-1 《数据结构与面向对象程序设计》实验九报告

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

    课程:《程序设计与数据结构》
    班级: 1823
    姓名: 刘颖洁
    学号:20182326
    实验教师:王志强
    实验日期:2019年12月2日
    必修/选修: 必修

    1.实验内容

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

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

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

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

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

    2. 实验过程及结果

    (1) 初始化:根据屏幕提示初始化无向图和有向图

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

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

    (4) 完成无向图的最小生成树,并输出

    (5) 完成有向图的单源最短路径求解

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

    • 问题1:prim算法的编写
    • 问题1解决方案:
    /*
     * prim最小生成树
     *
     * 参数说明:
     *   start -- 从图中的第start个元素开始,生成最小树
     */
    public void prim(int start) {
        int num = mVexs.length;         // 顶点个数
        int index=0;                    // prim最小树的索引,即prims数组的索引
        char[] prims  = new char[num];  // prim最小树的结果数组
        int[] weights = new int[num];   // 顶点间边的权值
    
        // prim最小生成树中第一个数是"图中第start个顶点",因为是从start开始的。
        prims[index++] = mVexs[start];
    
        // 初始化"顶点的权值数组",
        // 将每个顶点的权值初始化为"第start个顶点"到"该顶点"的权值。
        for (int i = 0; i < num; i++ )
            weights[i] = mMatrix[start][i];
        // 将第start个顶点的权值初始化为0。
        // 可以理解为"第start个顶点到它自身的距离为0"。
        weights[start] = 0;
    
        for (int i = 0; i < num; i++) {
            // 由于从start开始的,因此不需要再对第start个顶点进行处理。
            if(start == i)
                continue;
    
            int j = 0;
            int k = 0;
            int min = INF;
            // 在未被加入到最小生成树的顶点中,找出权值最小的顶点。
            while (j < num) {
                // 若weights[j]=0,意味着"第j个节点已经被排序过"(或者说已经加入了最小生成树中)。
                if (weights[j] != 0 && weights[j] < min) {
                    min = weights[j];
                    k = j;
                }
                j++;
            }
    
            // 经过上面的处理后,在未被加入到最小生成树的顶点中,权值最小的顶点是第k个顶点。
            // 将第k个顶点加入到最小生成树的结果数组中
            prims[index++] = mVexs[k];
            // 将"第k个顶点的权值"标记为0,意味着第k个顶点已经排序过了(或者说已经加入了最小树结果中)。
            weights[k] = 0;
            // 当第k个顶点被加入到最小生成树的结果数组中之后,更新其它顶点的权值。
            for (j = 0 ; j < num; j++) {
                // 当第j个节点没有被处理,并且需要更新时才被更新。
                if (weights[j] != 0 && mMatrix[k][j] < weights[j])
                    weights[j] = mMatrix[k][j];
            }
        }
    
        // 计算最小生成树的权值
        int sum = 0;
        for (int i = 1; i < index; i++) {
            int min = INF;
            // 获取prims[i]在mMatrix中的位置
            int n = getPosition(prims[i]);
            // 在vexs[0...i]中,找出到j的权值最小的顶点。
            for (int j = 0; j < i; j++) {
                int m = getPosition(prims[j]);
                if (mMatrix[m][n]<min)
                    min = mMatrix[m][n];
            }
            sum += min;
        }
        // 打印最小生成树
        System.out.printf("PRIM(%c)=%d: ", mVexs[start], sum);
        for (int i = 0; i < index; i++)
            System.out.printf("%c ", prims[i]);
        System.out.printf("
    ");
    }
    
    • 问题2:迪杰斯特拉算法的编写
    • 问题2解决方案:
    public void dijkstra(int vs, int[] prev, int[] dist) {
        // flag[i]=true表示"顶点vs"到"顶点i"的最短路径已成功获取
        boolean[] flag = new boolean[mVexs.length];
     
        // 初始化
        for (int i = 0; i < mVexs.length; i++) {
            flag[i] = false;          // 顶点i的最短路径还没获取到。
            prev[i] = 0;              // 顶点i的前驱顶点为0。
            dist[i] = mMatrix[vs][i];  // 顶点i的最短路径为"顶点vs"到"顶点i"的权。
        }
     
        // 对"顶点vs"自身进行初始化
        flag[vs] = true;
        dist[vs] = 0;
     
        // 遍历mVexs.length-1次;每次找出一个顶点的最短路径。
        int k=0;
        for (int i = 1; i < mVexs.length; i++) {
            // 寻找当前最小的路径;
            // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
            int min = INF;
            for (int j = 0; j < mVexs.length; j++) {
                if (flag[j]==false && dist[j]<min) {
                    min = dist[j];
                    k = j;
                }
            }
            // 标记"顶点k"为已经获取到最短路径
            flag[k] = true;
     
            // 修正当前最短路径和前驱顶点
            // 即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
            for (int j = 0; j < mVexs.length; j++) {
                int tmp = (mMatrix[k][j]==INF ? INF : (min + mMatrix[k][j]));
                if (flag[j]==false && (tmp<dist[j]) ) {
                    dist[j] = tmp;
                    prev[j] = k;
                }
            }
        }
     
        // 打印dijkstra最短路径的结果
        System.out.printf("dijkstra(%c): 
    ", mVexs[vs]);
        for (int i=0; i < mVexs.length; i++)
            System.out.printf("  shortest(%c, %c)=%d
    ", mVexs[vs], mVexs[i], dist[i]);
    }
    
    

    其他(感悟、思考等)

    • 复习了以前的知识(prim算法的写法和迪杰斯特拉算法)

    参考资料

  • 相关阅读:
    sql笔记
    [ACTF2020 新生赛]Include
    [极客大挑战 2019]Http
    [极客大挑战 2019]Knife
    [极客大挑战 2019]Secret File
    [HCTF 2018]admin
    [极客大挑战 2019]Havefun
    [RoarCTF 2019]Easy Calc
    ascll码转化
    《逆向工程核心原理》笔记第一章到第十一章
  • 原文地址:https://www.cnblogs.com/20182326lyj/p/12008063.html
Copyright © 2011-2022 走看看