1 / 20

台北總公司/台北縣汐止市新台五路一段 112 號 10 樓 A 棟

書名 Java 於資料結構與演算法之實習應用 書號  PG20098 原著  河西朝雄 著 譯者 周明憲 / 徐堯譯. 台北總公司/台北縣汐止市新台五路一段 112 號 10 樓 A 棟 Building A, 10F, 112, Shin-Tai-Wu Road Sec. 1, Shijr, Taipei, Taiwan. 電話/ 02-26962869  傳真/ 02-26962867 台中辦事處/台中市文心路一段 540 號 4 樓 -1 4-1F, 540, Wen Shing Road, Sec. 1, Taichung, Taiwan.

ozzie
Download Presentation

台北總公司/台北縣汐止市新台五路一段 112 號 10 樓 A 棟

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 書名 Java於資料結構與演算法之實習應用 書號 PG20098 原著 河西朝雄著 譯者 周明憲/徐堯譯 台北總公司/台北縣汐止市新台五路一段112號10樓A棟 Building A, 10F, 112, Shin-Tai-Wu Road Sec. 1, Shijr, Taipei, Taiwan. 電話/02-26962869 傳真/02-26962867 台中辦事處/台中市文心路一段540號4樓-1 4-1F, 540, Wen Shing Road, Sec. 1, Taichung, Taiwan. 電話/04-23287870 傳真/04-23108168 博碩網址:http://www.drmaster.com.tw

  2. 第七章 學習重點 • 簡單來說,幾個相連起來的樹的節點就稱為圖形。 • 以公路網為例,我們可將各地點(東京、橫濱、...)想像成節點,將各地點之間的距離或來往所需時間想像成分支(邊),如此即構成1個圖形。向公路網這樣各邊都有深厚定義的圖形稱為網路(network),很適合用來顯示日常的社會現象。舉例來說,如果我們知道如何找出公路網的最短路徑,就能從東京至大阪的公路網中找出最快抵達目的地的路線,這就解決了問題。

  3. 7-0 何謂圖形 • 圖形(graph)是指以邊(edge,分支:branch)將節點(node,頂點:vertex)連接起來的物件,其形式如下。這個圖形的意義為有通往1→2的路與通往2→1的路,但沒有通往1→3的路。 • 如要將這種圖形以資料形式表示出來,就要使用下列的相鄰矩陣(adjacency matrix)。 • 這個相鄰矩陣的各元素的值在指向節點i→節點j的邊存在的時候為1,否則為0。也有些方法在i=j時,將相鄰矩陣的各元素的值設為1,而不是設為0。本書則將此值設為0。 • 此外由於Java的陣列元素是由0開始,因此本書將0的元素設為未使用,將1的元素視為開始使用的元素。 • 邊若有方向則稱為有方向圖形(directed graph),以箭頭表示。 • 圖7.1所示的圖形的邊並無方向,這種圖形稱為無方向圖形(undirected graph)。 • 有方向圖形的相鄰陣列如下所示。在有方向圖形中,1→2是可通行的,但2→1則是無法通行的。

  4. 7-1 圖形的搜尋(深度優先) • 深度優先搜尋(depth first search)演算法的大致內容如下: ‧從起點出發,查出按編號由小到大的順序前進的位置,然後前進到無法前進(以邊連接之處或還未掃瞄)為止。 ‧若已無前路,則回到有前路的位置,然後再度前進值至無法前進為止。 ‧所有的前路都已走完後,便結束程式(回到來時路)

  5. private TextArea ta; private final int N=8; // 節點的數量 // 相鄰矩陣 private int[][] a={{0,0,0,0,0,0,0,0,0}, {0,0,1,0,0,0,0,0,0}, {0,1,0,1,1,0,0,0,0}, {0,0,1,0,0,0,0,1,0}, {0,0,1,0,0,1,0,0,0}, {0,0,0,0,1,0,1,0,0}, {0,0,0,0,0,1,0,1,1}, {0,0,0,1,0,0,1,0,1}, {0,0,0,0,0,0,1,1,0}}; private int[] v=new int[N+1]; // 查訪旗標 void visit(int i) { int j; v[i]=1; for (j=1;j<=N;j++) { if (a[i][j]==1 && v[j]==0) { ta.setText(ta.getText()+i+"->"+j+" "); visit(j); } } } ………

  6. public Rei51Frame() { setSize(300,100); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); Button bt; add(bt=new Button("圖形搜尋"),"North"); add(ta=new TextArea(5,40),"Center"); bt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int i; for (i=1;i<=N;i++) v[i]=0; visit(1); } }); }

  7. 7-2 圖形的搜尋(廣度優先) 廣度優先演算法的大致內容如下: • 將節點1存至佇列 • 取出節點1,將與節點相連接的未訪查節點(即2)存至佇列 • 取出節點2,以同樣方式將節點3、4、5按小至大順序存至佇列 • 取出節點7,將節點8存至佇列 • 節點6雖已取出,但由於沒有欲掃瞄的節點,因此佇列是空的。節點8也是一樣,當head=tail時,程式便結束。 節點6已拜訪過了,所以不置入

  8. private final int N=8; // 節點數量 private int[][] a={{0,0,0,0,0,0,0,0,0}, // 相鄰矩陣 {0,0,1,0,0,0,0,0,0}, {0,1,0,1,1,1,0,0,0}, {0,0,1,0,0,0,0,1,0}, {0,0,1,0,0,0,0,0,0}, {0,0,1,0,0,0,1,0,0}, {0,0,0,0,0,1,0,1,1}, {0,0,0,1,0,0,1,0,1}, {0,0,0,0,0,0,1,1,0}}; private int[] v=new int[N+1]; // 查訪旗標 private int[] queue=new int[100]; // 佇列 private int head=0, // 開頭資料的索引 tail=0; // 尾端資料的索引 public Rei52Frame() { setSize(300,150); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } });

  9. Button bt; add(bt=new Button("圖形的搜尋"),"North"); add(ta=new TextArea(5,40),"Center"); bt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int i,j; for (i=1;i<=N;i++) v[i]=0; queue[tail++]=1;v[1]=1; do { i=queue[head++]; // 從佇列中取出 for (j=1;j<=N;j++) { if (a[i][j]==1 && v[j]==0) { ta.setText(ta.getText()+i+"->"+j+" "); queue[tail++]=j; // 存至佇列 v[j]=1; } } } while (head!=tail); } ……………………

  10. 7-3 拓樸排序 • 假設有1~8件工作。要做第1件工作時,須先做好第2件工作。要做第3件工作時,須先做好第1件工作。要做第7件工作時,須先做好第3、6、8件工作。這種關係能以有方向圖形表示,其圖形如下: • 從上圖中我們可以瞭解,第1~8件工作可分為第2、1、3、4、7件工作與第2、5、4、6、7、8件工作等2組。第1件工作與第5件工作由於不同組,因此先執行哪個都無妨。像這種不一定能夠比較順序的情形稱為局部順序(partial order)。對於在局部順序中產生的資料,將第1件工作至最後1件工作排成1列的情形則稱為拓樸排序(topological sort)。由於這是順序的資料,因此不一定只有1個解答。

  11. 7-3 拓樸排序 • 拓樸排序針對有方向圖形進行深度優先搜尋,從目的地返回搜尋行經路線時,將節點取回。 先將節點1設為起點,再將與其連接的未掃瞄的節點以 1 3 (4) 3 (7) 3 (1) 的順序前進。打圈的節點為被取回的節點。然後將節點2設為起點,以 2 5 6 (8) (6) (5) (2) 的順序前進。 節點3、4、5、6、7、8也是以同樣的步驟操作,但因這些節點皆已掃瞄過,因此就直接結束。將取得的節點逆向排列後, 2、5、6、8、1、3、7、4 的順序即為應執行事項的順序。若改變起點的設定方式,則可得到其他的解。

  12. add(bt=new Button("拓樸排序"),"North"); add(ta=new TextArea(5,40),"Center"); bt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int i; for (i=1;i<=N;i++) v[i]=0; for (i=1;i<=N;i++) if (v[i]==0) visit(i); } });

  13. 7-4 Euler的一筆畫 • 歐拉(Euler)的一筆畫通過圖形的所有的邊後再回到原來位置,這條路線的追蹤就是Euler一筆畫。這觀念與一般的一筆畫問題是相同的。 將相連的邊的數量存入相鄰矩陣的各元素內。 使用深度優先搜尋作業便可製作出求一筆畫行經路線的演算法。 ‧一面將通過的路徑消去,一面走到無路可走。 ‧最後到達的地方即為起點,而且所有的邊若全部消去(這表示已經通過所有的邊),則到達此點的路線有1個解法。 ‧若已無去路,則將路徑復原(連接),依序返回,在搜尋下一個前進的位置。

  14. 從起點1出發在回到1的時候的具體範例如圖所示。從起點1出發在回到1的時候的具體範例如圖所示。

  15. private int success, n; // 通過路線的數目 private int[] v=new int[Root+1]; // 存有行經路線的堆疊 void visit(int i) { int j; v[n]=i; if (n==0 && i==Start) { // 通過邊並返回原位置 ta.setText(ta.getText()+"解"+(++success)+":"); for (i=0;i<=Root;i++) ta.setText(ta.getText()+v[i]+" "); ta.setText(ta.getText()+"\n"); } else { for (j=1;j<=Node;j++) { if (a[i][j]!=0) { a[i][j]--;a[j][i]--; // 將通過的路線切掉 n--; visit(j); a[i][j]++;a[j][i]++; // 將路線復原 n++; } } } }

  16. 7-5 最短路徑問題 • 例題55 戴克斯特拉法以戴克斯特拉法求出某起點至圖形上各點的最短距離 • 右側的圖形稱為網路(network)。這個圖形是指若將邊的長度視為道路的長度,則a→h的最短距離為a→d→g→h,其值為9。網路能以相鄰矩陣表示出來。矩陣中,需盡可能的將較大值M存至未相連的節點間的元素。

  17. 戴克斯特拉(Dijkstra)法 • 戴克斯特拉(Dijkstra)法為求某起點至圖形上各點的最短距離的方法之一,這個方法先從起點開始一一的確定至周邊節點的最短路徑,然後慢慢將範圍擴大,最後便求出至所有節點的最短路徑。其演算法大致內容如下: ‧求出起點至與其相連的節點的距離,然後在值最小的節點上標上記號。 ‧求出標上記號的節點至與其相連的節點的距離,再在其中找出距離最短的節點,然號標上記號。 ‧反覆做上述步驟直至所有節點都標上記號為止,最後得節點所得出的值就是從起點開始的最短距離。

  18. 戴克斯特拉法的具體範例如下: • 現在假設q點已標有記號,與q相連的點有r及p(假設p為已確定的點)。由於p為已確定的點,因此p≦q。正因為如此,通過q前往p點的距離便不可能比目前至p的距離還短。換句話說,通往已確定節點的距離不會受到更改。

  19. public void actionPerformed(ActionEvent e) { int j,k,p=0,start,min; int[] leng=new int[N+1], // 至節點的距離 v=new int[N+1]; // 確定旗標 ta.setText(""); start=Integer.parseInt(tf.getText()); for (k=1;k<=N;k++) { leng[k]=M;v[k]=0; } leng[start]=0; for (j=1;j<=N;j++) { min=M; // 搜尋最小的節點 for (k=1;k<=N;k++) { if (v[k]==0 && leng[k]<min) { p=k;min=leng[k]; } } v[p]=1; // 確定最小的節點 if (min==M) { ta.setText("圖形沒有連接\n"); return; } // 經由p至k的距離若比當時最短的距離小的話,便會執行更新作業 for (k=1;k<=N;k++) { if ((leng[p]+a[p][k])<leng[k]) leng[k]=leng[p]+a[p][k]; } } for (j=1;j<=N;j++) ta.setText(ta.getText()+start+" -> "+j+" : "+leng[j]+"\n"); } });

More Related