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

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

1.实验内容

完成图的综合实践
(1)初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图需要自己定义(顶点个数、边个数,建议先在草稿纸上画出图,然后再输入顶点和边数)
(2)图的遍历:完成有向图和无向图的遍历(深度和广度优先遍历)
(3)完成有向图的拓扑排序,并输出拓扑排序序列或者输出该图存在环
(4)完成无向图的最小生成树(Prim算法或Kruscal算法均可),并输出
(5)完成有向图的单源最短路径求解(迪杰斯特拉算法)

2. 实验过程及结果

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

 public Sorting(char[] dingdian, EData[] bian) {

        int lenv = dingdian.length;
        int elen = bian.length;

        // 初始化顶点
        mV= new N[lenv];
        for (int i = 0; i < mV.length; i++) {
            mV[i] = new N();
            mV[i].dingdian = dingdian[i];
            mV[i].firstX = null;
        }

        // 初始化边
        Enum = elen;
        for (int i = 0; i < elen; i++) {
            // 读取顶点
            char c1 = bian[i].start;
            char c2 = bian[i].end;
            int weight = bian[i].weight;
            int p1 = gPs(c1);
            int p2 = gPs(c2);
            B  node1 = new B ();
            node1.i = p2;
            node1.w = weight;
            //连接
            if(mV[p1].firstX == null)
                mV[p1].firstX = node1;
            else
                Connect(mV[p1].firstX, node1);
            B  node2 = new B ();
            node2.i = p1;
            node2.w = weight;
            //连接
            if(mV[p2].firstX == null)
                mV[p2].firstX = node2;
            else
                Connect(mV[p2].firstX, node2);
        }
    }

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

  • 深度优先遍历
private void DFS(int i, boolean[] BL) {
        B node;

        BL[i] = true;
        System.out.printf("%c ", mV[i].dingdian);
        node = mV[i].firstX;
        while (node != null) {
            if (!BL[node.i])
                DFS(node.i, BL);
            node = node.nextX;
        }
    }
  • 广度优先遍历
 public void BFS() {
        int head = 0;
        int rear = 0;
        int[] queue = new int[mV.length];            // 辅组队列
        boolean[] BL = new boolean[mV.length];  // 顶点访问标记
        for (int i = 0; i < mV.length; i++)
            BL[i] = false;

        System.out.printf("广度优先遍历: ");
        for (int i = 0; i < mV.length; i++) {
            if (!BL[i]) {
                BL[i] = true;
                System.out.printf("%c ", mV[i].dingdian);
                queue[rear++] = i;  // 入队列
            }

            while (head != rear) {
                int j = queue[head++];  // 出队列
                B node = mV[j].firstX;
                while (node != null) {
                    int k = node.i;
                    if (!BL[k])
                    {
                        BL[k] = true;
                        System.out.printf("%c ", mV[k].dingdian);
                        queue[rear++] = k;
                    }
                    node = node.nextX;
                }
            }
        }
        System.out.printf("\n");
    }

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

 public int TpSort() {
        int index = 0;
        int num = mV.length;
        int[] ins;               // 入度数组
        char[] tops;
        Queue<Integer> queue;

        ins   = new int[num];
        tops  = new char[num];
        queue = new LinkedList<Integer>();

        // 统计每个顶点的入度数
        for(int i = 0; i < num; i++) {

            B  node = mV[i].firstX;
            while (node != null) {
                ins[node.i]++;
                node = node.nextX;
            }
        }

        // 将所有入度为0的顶点入队列
        for(int i = 0; i < num; i ++)
            if(ins[i] == 0)
                queue.offer(i);                 // 入队列

        while (!queue.isEmpty()) {              // 队列非空
            int j = queue.poll().intValue();    // 出队列。j是顶点的序号
            tops[index++] = mV[j].dingdian;
            B  node = mV[j].firstX;
            while(node != null) {
                // 入度减1。
                ins[node.i]--;
                // 若入度为0,则入队列
                if( ins[node.i] == 0)
                    queue.offer(node.i);    // 入队列

                node = node.nextX;
            }
        }
        if(index != num) {
            System.out.printf("有向有环图\n");
            return 1;
        }
        // 打印拓扑排序结果
        System.out.printf("拓扑排序: ");
        for(int i = 0; i < num; i ++)
            System.out.printf("%c ", tops[i]);
        System.out.printf("\n");

        return 0;
    }
  1. 完成无向图的最小生成树(Prim算法或Kruscal算法均可),并输出
  • Kruscal算法
public void kruskal() {
        int index = 0;
        int[] v = new int[Enum];     // 保存终点。
        EData[] rets = new EData[Enum];  // 暂存结果数组
        EData[] e;                      // 对应的所有边

        e = getEdges();
        // 将边按权排序
        sortEdges(e, Enum);

        for (int i=0; i<Enum; i++) {
            int p1 = gPs(e[i].start);
            int p2 = gPs(e[i].end);

            int m = getEnd(v, p1);
            int n = getEnd(v, p2);
            // 如果m!=n,则没有形成环路
            if (m != n) {
                v[m] = n;
                rets[index++] = e[i];
            }
        }
}

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

public void dijkstra(int s, int[] q, int[] t) {
        // flag[i]=true表示最短路径已成功获取。
        boolean[] flag = new boolean[mV.length];

        // 初始化
        for (int i = 0; i < mV.length; i++) {
            flag[i] = false;
            q[i] = 0;                // 顶点i的前驱顶点为0。
            t[i] = getWeight(s, i);
        }

        // 初始化
        flag[s] = true;
        t[s] = 0;


        int k = 0;
        for (int i = 1; i < mV.length; i++) {
            // 寻找当前最小的路径;
            // 寻找当前最小的路径;
            // 寻找当前最小的路径;
            int min = INF;
            for (int j = 0; j < mV.length; j++) {
                if (flag[j]==false && t[j]<min) {
                    min = t[j];
                    k = j;
                }
            }
            // 获取到最短路径
            flag[k] = true;
            for (int j = 0; j < mV.length; j++) {
                int tmp = getWeight(k, j);
                tmp = (tmp==INF ? INF : (min + tmp)); // 防止溢出
                if (flag[j]==false && (tmp<t[j]) )
                {
                    t[j] = tmp;
                    q[j] = k;
                }
            }
        }
  • 实验结果截图

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

  • 问题1:try异常导致程序锁死。

  • 问题1解决方案:解决时发现不止我一个人有这个问题。参照博客发现是
e.printStackTrace()

其他(感悟、思考等)

最后一个小实验,个人认为图的理解比树简单一点,并且可以利用到离散中学过的知识。java结课意味着接下来可以安心复习期末和准备app了。

参考资料

12-24 20:56