十字鏈表:十字鏈表(Orthogonal List)是有向圖的另外一種鏈式存儲結構。該結構能夠當作是將有向圖的鄰接表和逆鄰接表結合起來獲得的
html
BFS算法之因此叫作廣度優先搜索,是由於它始終將已發現的頂點和未發現的之間的邊界,沿其廣度方向向外擴展。亦即,算法首先會發現和s距離爲k的全部頂點,而後纔會發現和s距離爲k+1的其餘頂點。同深度優先搜索相反,BFS寬度優先搜索每次選擇深度最淺的節點優先擴展。而且當問題有解時,寬度優先算法必定可以找到解,而且在單位耗散時間的狀況下,能夠保證找到最優解。java
圖的最小生成樹:個有n個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原圖中的全部n個結點,而且有保持圖連通的權值和邊最小git
問題1:如何用Java具體實現深度遍歷算法
import java.util.Stack; public class Graph { //節點個數 private static int number = 8; //創立訪問標誌數組的布爾型數組 private boolean[] flag; //創立要遍歷節點的數組 private int[] num= {1,2,3,4,5,6,7,8}; //創立這幾個數字的鄰接矩陣 private int[][] edges = { {0, 1, 1, 0, 0, 0, 0, 0}, {1, 0, 0, 1, 1, 0, 0, 0}, {1, 0, 0, 0, 0, 1, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 1}, {0, 1, 0, 0, 0, 0, 0, 1}, {0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, }; void DFSTraverse() { //設置一個和數字個數同等大小的布爾數組 flag = new boolean[number] ; //從頂點開始,實現深度遍歷 for (int i = 0; i < number; i++) { if (flag[i] == false) { // 若是當前頂點沒有被訪問,進入DFS DFS(i); } } } //完成一次遍歷,直到後面無鏈接節點 void DFS(int i) { // 標記第num[i]個節點被訪問 flag[i] = true; //將該節點打印 System.out.print(num[i] + " "); //尋找與num[i]節點相連的下一個訪問節點 for (int j = 0; j < number; j++) { //從標誌數組第0位開始順序查找,若是這一點未被訪問,且與第num[i]個節點相連 if (flag[j] == false && edges[i][j] == 1) { //遞歸 DFS(j); } } } void DFS_Map(){ flag = new boolean[number]; Stack<Integer> stack =new Stack<Integer>(); for(int i=0;i<number;i++){ if(flag[i]==false){ flag[i]=true; System.out.print(num[i]+" "); stack.push(i); } while(!stack.isEmpty()){ int k = stack.pop(); for(int j=0;j<number;j++){ if(edges[k][j]==1&&flag[j]==false){ flag[j]=true; System.out.print(num[j]+" "); stack.push(j); break; } } } } } //測試類 public static void main(String[] args) { Graph graph = new Graph(); System.out.println("DFS遞歸:"); graph.DFSTraverse(); System.out.println(); System.out.println("DFS非遞歸:"); graph.DFS_Map(); } }
public class GraphKruskal { //定義Edge型數組 private Edge[] edges; private int edgeSize; public GraphKruskal(int edgeSize) { //參數個數 this.edgeSize = edgeSize; edges = new Edge[edgeSize]; createEdgeKruskal(); } //建立邊的集合,從小到大 private void createEdgeKruskal() { Edge edge0 = new Edge(1, 3, 1); Edge edge1 = new Edge(4, 6, 2); Edge edge2 = new Edge(2, 5, 3); Edge edge3 = new Edge(3, 6, 4); Edge edge4 = new Edge(2, 3, 5); Edge edge5 = new Edge(3, 4, 5); Edge edge6 = new Edge(1, 4, 5); Edge edge7 = new Edge(3, 5, 6); Edge edge8 = new Edge(1, 2, 6); Edge edge9 = new Edge(5, 6, 6); edges[0] = edge0; edges[1] = edge1; edges[2] = edge2; edges[3] = edge3; edges[4] = edge4; edges[5] = edge5; edges[6] = edge6; edges[7] = edge7; edges[8] = edge8; edges[9] = edge9; } //kruskal算法建立最小生成樹 public void createMinSpanTreeKruskal() { // 定義一個一維數組,下標爲連線的起點,值爲連線的終點 int[] parent = new int[edgeSize]; for (int i = 0; i < edgeSize; i++) { parent[i] = 0; } int sum = 0; //將數組中每個元素都賦給左邊 for (Edge edge : edges) { // 找到起點和終點在臨時連線數組中的最後鏈接點,核心 int start = find(parent, edge.start); int end = find(parent, edge.end); // 經過起點和終點找到的最後鏈接點是否爲同一個點,是則產生迴環 if (start != end) { // 沒有產生迴環則將臨時數組中,起點爲下標,終點爲值 parent[start] = end; System.out.println("訪問到了節點:{" + start + "," + end + "},權值:" + edge.weight); sum += edge.weight; } } System.out.println("最小生成樹的權值總和:" + sum); } // 獲取集合的最後節點 private int find(int parent[], int index) { while (parent[index] > 0) { index = parent[index]; } return index; } //鏈接頂點的邊 class Edge { private int start; private int end; private int weight; public Edge(int start, int end, int weight) { this.start = start; this.end = end; this.weight = weight; } } public static void main(String[] args) { GraphKruskal graphKruskal = new GraphKruskal(10); graphKruskal.createMinSpanTreeKruskal(); } }
public class Dijkstra { public static final int M = 10000; // 表明正無窮 public static void main(String[] args) { // 二維數組每一行分別是 A、B、C、D、E 各點到其他點的距離, // A -> A 距離爲0, 常量M 爲正無窮 int[][] weight1 = { {0, 13, 8, M, 30, M, 32}, {M, 0, M, M, M, 9, 7 }, {M, M, 0, 5, M, M , M}, {M, M, M, 0, 6, M , M}, {M, M, M, M, 0, 2 , M}, {M, M, M, M, M, 0 ,17}, {M, M, M, M, M, M , 0}, }; int start = 0; int[] shortPath = dijkstra(weight1, start); for (int i = 0; i < shortPath.length; i++) System.out.println("從" + start + "出發到" + i + "的最短距離爲:" + shortPath[i]); } public static int[] dijkstra(int[][] weight, int start) { // 接受一個有向圖的權重矩陣,和一個起點編號start(從0編號,頂點存在數組中) // 返回一個int[] 數組,表示從start到它的最短路徑長度 int n = weight.length; // 頂點個數 int[] shortPath = new int[n]; // 保存start到其餘各點的最短路徑 String[] path = new String[n]; // 保存start到其餘各點最短路徑的字符串表示 for (int i = 0; i < n; i++) path[i] = new String(start + "-->" + i); int[] visited = new int[n]; // 標記當前該頂點的最短路徑是否已經求出,1表示已求出 // 初始化,第一個頂點已經求出 shortPath[start] = 0; visited[start] = 1; for (int count = 1; count < n; count++) { // 要加入n-1個頂點 int k = -1; // 選出一個距離初始頂點start最近的未標記頂點 int dmin = Integer.MAX_VALUE; for (int i = 0; i < n; i++) { if (visited[i] == 0 && weight[start][i] < dmin) { dmin = weight[start][i]; k = i; } } // 將新選出的頂點標記爲已求出最短路徑,且到start的最短路徑就是dmin shortPath[k] = dmin; visited[k] = 1; // 以k爲中間點,修正從start到未訪問各點的距離 for (int i = 0; i < n; i++) { //若是 '起始點到當前點距離' + '當前點到某點距離' < '起始點到某點距離', 則更新 if (visited[i] == 0 && weight[start][k] + weight[k][i] < weight[start][i]) { weight[start][i] = weight[start][k] + weight[k][i]; path[i] = path[k] + "-->" + i; } } } for (int i = 0; i < n; i++) { System.out.println("從" + start + "出發到" + i + "的最短路徑爲:" + path[i]); } System.out.println("====================================="); return shortPath; } }
(數組
)網絡
教材學習中的問題和解決過程, 一個問題加1分數據結構
代碼調試中的問題和解決過程, 一個問題加1分學習
基於評分標準,我給本博客打分:18分測試
參考示例this
數據結構學習也算到尾聲了,圖這一章算法比較豐富,須要咱們花費時間逐一認真理解,並落實到代碼實現。只有這樣,咱們對數據結構的理解才能真正融會貫通
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 200/200 | 2/2 | 20/20 | |
第二週 | 300/500 | 2/4 | 18/38 | |
第三週 | 500/1000 | 3/7 | 22/60 | |
第四周 | 300/1300 | 2/9 | 30/90 | |
第五週 | 1600/2900 | 2/11 | 20/110 | |
第六週 | 981 /3881 | 2/12 | 25/135 | |
第七週 | 1700/5518 | 3/15 | 45/180 | |
第八週 | 700/6200 | 2/17 | 20/200 | |
第九周 | 4300/10500 | 2/19 | 30/230 | |
第十週 | 2064/12564 | 1/20 | 30/260 |
嘗試一下記錄「計劃學習時間」和「實際學習時間」,到期末看看能不能改進本身的計劃能力。這個工做學習中很重要,也頗有用。
耗時估計的公式:Y=X+X/N ,Y=X-X/N,訓練次數多了,X、Y就接近了。
計劃學習時間:30小時
實際學習時間:30小時
改進狀況:
(有空多看看現代軟件工程 課件
軟件工程師能力自我評價表)