20182330 2019-2020-1 《數據結構與面向對象程序設計》實驗九報告

20182330 2019-2020-1 《數據結構與面向對象程序設計》實驗九報告

課程:《程序設計與數據結構》
班級: 1823
姓名: 魏冰妍
學號:20182330
實驗教師:王志強
實驗日期:2019年12月2日
必修/選修: 必修html

1.實驗內容

完成圖的綜合實踐
(1)初始化:根據屏幕提示(例如:輸入1爲無向圖,輸入2爲有向圖)初始化無向圖和有向圖(可用鄰接矩陣,也可用鄰接表),圖須要本身定義(頂點個數、邊個數,建議先在草稿紙上畫出圖,而後再輸入頂點和邊數)
(2)圖的遍歷:完成有向圖和無向圖的遍歷(深度和廣度優先遍歷)
(3)完成有向圖的拓撲排序,並輸出拓撲排序序列或者輸出該圖存在環
(4)完成無向圖的最小生成樹(Prim算法或Kruscal算法都可),並輸出
(5)完成有向圖的單源最短路徑求解(迪傑斯特拉算法)java

2. 實驗過程及結果

1.初始化:根據屏幕提示(例如:輸入1爲無向圖,輸入2爲有向圖)初始化無向圖和有向圖(可用鄰接矩陣,也可用鄰接表),圖須要本身定義(頂點個數、邊個數,建議先在草稿紙上畫出圖,而後再輸入頂點和邊數)node

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異常致使程序鎖死。app

  • 問題1解決方案:解決時發現不止我一我的有這個問題。參照博客發現是e.printStackTrace()。因而刪掉 e.printStackTrace() ,異常處理。學習

    短期內大量請求訪問此接口 -> 代碼自己有問題,不少狀況下拋異常 -> e.printStackTrace() 來打印異常到控制檯 -> 產生錯誤堆棧字符串到字符串池內存空間 -> 此內存空間一會兒被佔滿了 -> 開始在此內存空間產出字符串的線程還沒徹底生產完整,就沒空間了 -> 大量線程產出字符串產出到一半,等在這兒(等有內存了繼續搞啊)-> 相互等待,等內存,鎖死了,整個應用掛掉了。.net

其餘(感悟、思考等)

最後一個小實驗,我的認爲圖的理解比樹簡單一點,而且能夠利用到離散中學過的知識。java結課意味着接下來能夠安心複習期末和準備app了。線程

參考資料

相關文章
相關標籤/搜索