1. 程式人生 > 其它 >20202315 實驗九《資料結構與面向物件程式設計》實驗報告

20202315 實驗九《資料結構與面向物件程式設計》實驗報告

課程:《程式設計與資料結構》
班級: 2023
姓名: 王夢欣
學號:20202315
實驗教師:王志強
實驗日期:2021年12月21日
必修/選修: 必修

## 1.實驗內容

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

PS:本題12分。目前沒有明確指明圖的頂點和連通邊,如果雷同或抄襲,本次實驗0分。
實驗報告中要根據所編寫的程式碼解釋圖的相關演算法

## 2.實驗過程及結果

(1) 初始化:根據螢幕提示(例如:輸入1為無向圖,輸入2為有向圖)初始化無向圖和有向圖(可用鄰接矩陣,也可用鄰接表),圖需要自己定義(頂點個數、邊個數,建議先在草稿紙上畫出圖,然後再輸入頂點和邊數)

·這裡我使用的是鄰接矩陣實現無向圖及有向圖的初始化

碼雲連結:

在草稿紙上畫出圖,如下:

執行結果截圖如下:

(2) 圖的遍歷:完成有向圖和無向圖的遍歷(深度和廣度優先遍歷)

主要程式碼:

//得到第一個鄰接結點的下標
    public
int getFirstNeighbor(int index){ for (int j=0;j<numvex;j++){ if(side[index][j]>0){ return j; } } return -1; } //根據前一個鄰接結點的下標來確定下一個鄰接結點 public int getNextNeighbor(int v1,int v2){ for(int j=v2+1;j<numvex;j++){
if(side[v1][j]>0){ return j; } } return -1; } //私有函式,深度優先遍歷 private void depthFirstSearch(boolean[] isVisited,int i){ //首先訪問該結點,在控制檯打印出來,置該結點為已訪問 System.out.print(vex[i]+" "); isVisited[i]=true; int w=getFirstNeighbor(i); while(w!=-1){ if(!isVisited[w]){ depthFirstSearch(isVisited,w); } w=getNextNeighbor(i,w); } } //對外公開函式,深度優先遍歷,與其同名私有函式屬於方法過載 public void depthFirstSearch(){ boolean[] isVisited = new boolean[100]; for(int i=0;i<numvex;i++){ if(!isVisited[i]){ depthFirstSearch(isVisited,i); } } } //私有函式,廣度優先遍歷 private void broadFirstSearch(boolean[] isVisited,int i){ int u,w; LinkedList quene = new LinkedList(); //首先訪問該結點,置該結點為已訪問 System.out.print(vex[i]+" "); isVisited[i]=true; //結點進入佇列 quene.addLast(i); while (!quene.isEmpty()){ u=((Integer)quene.removeFirst()).intValue(); w=getFirstNeighbor(u); while(w!=-1){ if(!isVisited[w]){ //訪問該結點、標記併入佇列 System.out.print(vex[w]+" "); isVisited[w]=true; quene.addLast(w); } //尋找下一個鄰接結點 w=getNextNeighbor(u,w); } } } //對外公開函式,廣度優先遍歷 public void broadFirstSearch(){ boolean[] isVisited = new boolean[100]; for(int i=0;i<numvex;i++){ if(!isVisited[i]){ broadFirstSearch(isVisited,i); } } }

執行結果截圖:

(3) 完成有向圖的拓撲排序,並輸出拓撲排序序列或者輸出該圖存在環

實現該功能的過程十分曲折,多次除錯之後才發現問題出在一個很小的點上,由於我每次輸入結點都是1,2,3,4...,所以想當然的將其與陣列的【1】【2】【3】...對應

除錯之後才發現這一細節問題所在。

主要程式碼:

//拓撲排序
    public void topoSorting(){
        System.out.println("拓撲排序:");
        int a=0;
        Stack stack = new Stack();
        int[] num=new int[numvex];
        for(int j=0;j<numvex;j++){
            num[j] = 0;
            for(int i=0;i<numvex;i++){
                num[j]=num[j]+side[i][j];
            }
            if(num[j]==0){
                stack.push(vex[j]);
                num[j]=-1;
            }
        }
        while (!stack.isEmpty()){
            System.out.print(stack.peek()+"   ");
            a++;
            int m=(Integer) stack.peek();
            stack.pop();
            for(int j=0;j<numvex;j++){
                if(side[m-1][j]>0) {
                    num[j] = num[j] - 1;
                }
                if(num[j]==0){
                    stack.push(vex[j]);
                    num[j]=-1;
                }
            }
        }
        if(a==numvex)
            System.out.println("拓撲排序完成");
        else
            System.out.println("該有向圖有環");
    }

執行實現截圖: