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) 圖的遍歷:完成有向圖和無向圖的遍歷(深度和廣度優先遍歷)
主要程式碼:
//得到第一個鄰接結點的下標 publicint 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("該有向圖有環"); }
執行實現截圖: