1 / 33

台北總公司/台北縣汐止市新台五路一段 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.

moe
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. 第三章 學習重點 • 數值分析計算與大量的資料處理都是電腦的重要工作。資料處理的基本作業有排序(sort)與搜尋(search)。 • 排序的方法有基本型及其改良型,前者包括,直接選擇法、氣泡排序與基本插入法等,後者則有Shell排序。本章將會說明這些排序方法。至於更高速的排序方法,如快速排序與堆積排序則會在第4章與第6章說明。 • 在搜尋的方法方面,本章將會說明逐筆搜尋與2元搜尋,同時也會說明較特殊且高速的搜尋方法——Hash。而2元搜尋樹搜尋法則將會在第6章說明。 • 本章也會說明將2組資料列合而為一的合併(merge)、字串的取代(replace)與字串的核對(pattern matching)。

  3. 3-0何謂排序與搜尋 • 排序(sort)排序為將資料按照一定的規則予以排列之意。1、5、11、20…之類由小排到大的順序稱為遞增順序,…20、11、5、1之類由大排到小的順序則稱為遞減順序。 • 搜尋(search)從大量的資料中找出必要資料的作業稱為搜尋(search)。搜尋的方法可大致分為逐筆搜尋法與2元搜尋法。

  4. 3-1 基本排序 • 從數列中找出最小項次,再與a1交換,如此從開始反覆操作直至數列成為a1為止的作業稱為直接選擇法排序。 • 將過程製作成演算法後,其內容如下: (1)將對象項i從0移至,並反覆操作系列步驟。 (2)將對象項設為初始值(最小值)。 (3)關於對象項項,則反覆操作下列步驟。 (4)找出最小項,在s中求出其項次編號。 (5)將i項與s項交換。

  5. public void paint(Graphics g) { final int N=6; // 資料數 int[] a={80,41,35,90,40,20}; int min,s,t,i,j; for (i=0;i<N-1;i++) { min=a[i]; s=i; for (j=i+1;j<N;j++) { if (a[j]<min) { min=a[j]; s=j; } } t=a[i];a[i]=a[s];a[s]=t; } for (i=0;i<N;i++) g.drawString(""+a[i],i*20,20); } }

  6. 3-1 氣泡排序 • 比較相鄰的2項資料,下面(後面)的資料項若比上面(前面)的資料項小,則反覆進行這2個資料項更換作業。由於較小的資料項恰似氣泡由下往上升的樣子,因此稱為氣泡排序。

  7. public void paint(Graphics g) { final int N=6; // 資料數 int[] a={80,41,35,90,40,20}; int t,i,j; for (i=0;i<N-1;i++) { for (j=N-1;j>i;j--) { if (a[j]<a[j-1]) { t=a[j];a[j]=a[j-1];a[j-1]=t; } } } for (i=0;i<N;i++) g.drawString(""+a[i],i*20,20); } }

  8. 3-1 shaker排序 • 氣泡排序由於不論述列是否正確排列皆會無條件的反覆進行比較,因此效率較差。如果由數列的前方(左側)開始掃瞄至交換為止的位置為i與i+1,則i+1~n-1的元素由於應已正確排列,因此無須再次掃瞄。為此,我們可將最後交換的位置儲存至shift,並將此位置設為下次掃瞄時的範圍。 • 不過要是有小的元素位於右端,則最後的交換均會在數列的後方進行,上面的shift的效果就少得很多。因此掃瞄的方向就要改為由左至右及由右至左雙向交互進行。這就是shaker排序。

  9. public void paint(Graphics g) { final int N=9; // 資料數 int[] a={3,5,6,9,2,7,8,10,4}; int left,right,i,shift=0,t; left=0;right=N-1; while (left<right) { for (i=left;i<right;i++) { if (a[i]>a[i+1]) { t=a[i];a[i]=a[i+1];a[i+1]=t; shift=i; } } right=shift; for (i=right;i>left;i--) { if (a[i]<a[i-1]) { t=a[i];a[i]=a[i-1];a[i-1]=t; shift=i; } } left=shift; } for (i=0;i<N;i++) g.drawString(""+a[i],i*20,20); } }

  10. 3-2 Shell排序 • 基本插入法的原理為將數列的視為已排列整齊的數列,再查出應放入此數列的哪個位置,然後再將其插入至此位置。這個步驟只要將i在1至反覆操作即可。 • 至於要放在數列的哪個位置,則只要由數列的右端開始,在比數列記錄項較小的空間中反覆執行交換作業。

  11. public void paint(Graphics g) { final int N=100; // 資料數 int i,j,t; int[] a=new int[N]; for (i=0;i<N;i++) // N個亂數 a[i]=(int)(1000*Math.random()+1); for (i=1;i<N;i++) { for (j=i-1;j>=0;j--) { if (a[j]>a[j+1]) { t=a[j];a[j]=a[j+1];a[j+1]=t; } else break; } } int y=0; for (i=0;i<N;i++) { if (i%14==0) y++; g.drawString(""+a[i],(i%14)*30,y*20); } } }

  12. 3-2 shell排序 • 不以基本插入法一口氣將數列a0, a1, a2, ..., an-1做排序,而按一定的間隔(gap)將數列分成數個數列,再逐一以基本插入法做排序。像這樣一面將一部份的數列大略做排序,一面將一部份的數列收斂至全部數列(將gap設為1)後,最後的排序作業即告結束。也就是說,在適用gap=1的基本插入法以前,先將較小的元素大略的排列至前面,較大的元素則排列至後面,以減低比較與交換的次數,這種方式稱為shell排序。這個名稱是取自提出此方法的Shell。 • gap的決定方式中有最佳的方式,不過這裡僅單純的說明將gap劃分一半的方法。

  13. 3-2 shell排序 • 我們以圖3.8為例。假設資料有8個,則最初的gap為8/2=4,然後將4個間隔的數列(51,45)、(60,70)、...逐一以基本插入法進行排序。 • 接下來將gap設為4/2=2,在將2個間隔的數列(45,55,51,80)、(60,21,70,30)逐一以基本插入法進行排序。 • 然後接下來將gap設為2/2=2,在將1個間隔的數列(45,21,...)以基本插入法進行排序。由於gap=1的數列為全部數列,因此排序作業就此結束。 上圖中gap=2時的數列有以下2組: 01234567 ○□○□○□○□

  14. 3-2 shell排序 • 如製作成演算法,則其大致內容如下: (1)設定gap的初始值(N/2) (2)反覆操作以下步驟直至gap的值為1。 (3)gap間隔的數列共有gap個,因此反覆操 作的次數為此gap個數以下 (4)以基本插入法將gap間隔的數列 (aj, aj+gap, aj+2gap,...)進行排序

  15. 3-2 Shell排序的改良 • gap的選定方法一般來說,將gap系統選為可互為基礎的方法是最有效率的方法,而更簡單的方法有:使用..., 121, 40, 13, 4, 1這類數列的方法。gap的初始值為從資料數N以內的前面之數列中選出的最大值,而像練習問題19中以..., 8, 4, 2, 1之類的2的2次方來取出gap後,效率就變得較差。 • 資料的區域參考性將數列○□○□○□○□分成○○○○與□□□□這2個數列,再以基本插入法分別進行排序時,由於陣列元素的參考會分散,因此記憶存取的效率就會很差。如要查詢大量資料時,最好查詢連續的資料區塊,這樣存取的效率會比較好。這種情形稱為區域參考(local reference)。

  16. 3-3 逐筆搜尋與衛兵 • 逐筆搜尋是指從儲存於陣列等的資料之開頭起,依序逐一搜尋所要找的資料,當找到所要的資料後,便停止搜尋作業,是一種單純的搜尋法。 • 設衛兵以設衛兵的方式來改進結束判斷的設定。

  17. 逐筆搜尋--- public void actionPerformed(ActionEvent e) { final int N=10; // 資料數 int i; Girl[] a={new Girl("Ann",18),new Girl("Rolla",19), new Girl("Nancy",16),new Girl("Eluza",17), new Girl("Juliet",18),new Girl("Machilda",20), new Girl("Emy",15),new Girl("Candy",16), new Girl("Ema",17),new Girl("Mari",18)}; String key=tf.getText(); i=0; while (i<N && !key.equals(a[i].name)) i++; if (i<N) ta.setText(ta.getText()+a[i].name+","+a[i].age+"\n"); else ta.setText(ta.getText()+key+"的資料找不到\n"); }

  18. 設衛兵--- public void actionPerformed(ActionEvent e) { final int N=10; // 資料數 int i; Girl[] a={new Girl("Ann",18),new Girl("Rolla",19), new Girl("Nancy",16),new Girl("Eluza",17), new Girl("Juliet",18),new Girl("Machilda",20), new Girl("Emy",15),new Girl("Candy",16), new Girl("Ema",17),new Girl("Mari",18), new Girl("",0)}; // 衛兵 String key=tf.getText(); a[N]=new Girl(key,0); i=0; while (!key.equals(a[i].name)) i++; if (i<N) ta.setText(ta.getText()+a[i].name+","+a[i].age+"\n"); else ta.setText(ta.getText()+key+"的資料找不到\n"); }

  19. 3-4 2元搜尋 • 2元搜尋法為在資料按遞增順序或遞減順序排列時有效的搜尋法。 • 我們將搜尋範圍的上下限分別設為upper與low,然後將位於x=(low+upper)/2位置的資料與鍵值(欲搜尋的鍵值)做一比較。若鍵值較大,則鍵值的位置應位於x的上面,因此low便為x+1。反之,若鍵值較小,則鍵值的位置應位於x的下面,因此low便為x-1。如此在low≦ upper之間反覆操作這個步驟。

  20. 3-4 2元搜尋 實際搜尋範例: • (1) 起先由於low=0,upper=9,因此x=(0+9)/2=4,然後將第4個的資料31與欲搜尋的資料50做一比較,由於50比31大,因此low=4+1=5。 • (2) 當low=5,upper=9時,x=(5+9)/2=7,然後將第7個的資料70與欲搜尋的資料50做一比較,由於50比70小,因此upper=7-1=6。 • (3) 當low=5,upper=6時,x=(5+6)/2=5,然後將第5個的資料50與欲搜尋的資料50做一比較,而找出欲搜尋的資料。

  21. public void actionPerformed(ActionEvent e) { final int N=10; // 資料數 int[] a={2,3,7,11,31,50,55,70,77,80}; int key,low,high,mid,flag=0; key=Integer.parseInt(tf.getText()); low=0;high=N-1; while (low<=high) { mid=(low+high)/2; if (a[mid]==key) { ta.setText(ta.getText()+a[mid]+"在第"+mid+"個位置\n"); flag=1; break; } if (a[mid]<key) low=mid+1; else high=mid-1; } if (flag!=1) ta.setText(ta.getText()+key+"沒找到\n"); }

  22. 3-5 合併 • 合併(merge)是指將經排序過的2組(或3組以上)的資料組合成1個經過同樣排序的資料。 • 設a、b為經過排序的2組資料,c為新的資料,各資料的開頭編號各為i、j、p,合併演算法的大致內容如下: (1)反覆操作下列步驟至資料a或b的尾端。 (2)比較ai與bj,將較小的一方複製至cp,然後將較小方的資料的編號向前推進1位。 (3)將尾端為止的資料複製至c。

  23. public void paint(Graphics g) { final int M=10, // a[]的資料數 N=5; // b[]的資料數 int i=0,j=0,p=0; int[] a={2,4,5,7,8,10,15,20,30,40}, b={6,11,25,33,35}, c=new int[M+N]; while (i<M && j<N) { // 當還未達到a[],b[]的尾端時 if (a[i]<=b[j]) c[p++]=a[i++]; else c[p++]=b[j++]; } while (i<M) // 直到a[]的尾端 c[p++]=a[i++]; while (j<N) // 直到b[]的尾端 c[p++]=b[j++]; for (i=0;i<M+N;i++) g.drawString(""+c[i],i*20,20); } }

  24. 3-6 字串的核對(pattern matching) • 設文字text內含有欲核對的字串key。 如欲從text之中找出key,可先從text的開頭起逐字與key做比較。 如發現到key,方法search會傳回key在text中的位置,如果搜尋到text的結尾(正確來說應是text的結尾至key的長度前的位置)卻未找到key,方法search便會傳回-1的值。

  25. …… int search(int p,String text,String key) { int i,m,n; m=text.length(); n=key.length(); for (i=p;i<=m-n;i++) { if ((text.substring(i,i+n)).equals(key)) return i; } return -1; } ……… bt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String text="This is a pen. That is a pencil."; String key=tf.getText(); int m,n,p; m=text.length(); n=key.length(); p=search(0,text,key); while (p!=-1){ ta.setText(ta.getText()+text.substring(p,m)+"\n"); p=search(p+n,text,key); }

  26. 3-6 鍵值字串與區分字元 • 如要讓程式瞭解pen與pencil、sharpen的pen之不同,只要在字串pen被找到時,讓pen的前後字串為區分字元(空格或.)即可。pen的位置若在文字的開頭或結尾時,(1)部分的程式寫法如下: if ((text.substring(i,i+n)).equals(key)) { if (i==p || i==m-n) return i; String f=text.substring(i-1,i); String b=text.substring(i+n,i+n+1); if ((f.equals(" ") || f.equals(".")) && (b.equals(" ") || b.equals("."))) return i; }

  27. 3-6 Boyer-Moore法 • Boyer-Moore法則以字串與鍵值的右端為基準進行核對作業,當這2者不相符時,並不向前推進1個字元,而是向欲核對字元的右端的字元之值前進。 • Boyer-Moore法演算法的大致內容如下: (1) 製作「前進值」表。 (2)核對完text以前,反覆操作以下步驟。 (3)如text中的p位置的字元與key右邊的字元(以key[n-1]表示)一致的話,就將以p-n+1為首位的n字元的字串與key比較,若一致的話,即為p-n+1所求的位置。 (4)將位置p向後移動「前進值」所定的字元。

  28. ……… int search(int p,String text,String key) { int i,m,n; m=text.length(); n=key.length(); while (p<m) { if ((text.substring(p-n+1,p+1)).equals(key)) return p-n+1; p=p+skip[text.charAt(p)]; // 將搜尋位置向前推進 } return -1; // 若沒找到 } void table(String key) { // 製作跳躍表 int k,n; n=key.length(); for (k=0;k<=255;k++) skip[k]=n; for (k=0;k<n-1;k++) skip[key.charAt(k)]=n-k-1; } ………

  29. 3-7 字串的取代 • 從text中找出key字串的內容,再以字串rep的內容取代key字串的內容。

  30. ……… int search(int p,String text,String key) { int i,m,n; m=text.length(); n=key.length(); for (i=p;i<=m-n;i++) { if ((text.substring(i,i+n)).equals(key)) return i; } return -1; } String replace(String text,String key,String rep) { int p; String d1,d2; p=search(0,text,key); while (p!=-1) { d1=text.substring(0,p); d2=text.substring(p+key.length(),text.length()); text=d1+rep+d2; p=search(p+rep.length(),text,key); } return text; } ……

  31. 3-8 Hash(雜湊) • 假設有一個班級的學生資料,如要以學號管理這些資料,只要將這班學生的學號設為記錄編號並存入陣列(檔案),便可立即以記錄編號基礎來參考這些資料。 • 不過,有些資料無法以編號來管理,這時一般都將姓名等非數值資料設為鍵值,再進行搜尋,否則無法將資料參考起來。

  32. 3-8 Hash函數 • 我們將由英文大寫字母組成的姓名設為鍵值,將這些鍵值的名稱設為A1、A2、A3...、An,共有n個字元。若將鍵值的長度設為n個字元,則所能取得的姓名組合便有26n+1個,這是1個很大的數值範圍。因此我們使用鍵值開頭的A1、鍵值中間的An/2與鍵值倒數第2位的An-1這3個字元,來設定下列的函數。 • 假設鍵值為“SUZUKI”,則 • 因此只要將數值428視為陣列的元素或檔案的紀錄編號,再對應至SUZUKI即可。

  33. ……… int hash(String s) { // Hash函數 final int ModSize=1000; int n; n=s.length(); return (s.charAt(0)-'A'+(s.charAt(n/2-1)-'A')*26 +(s.charAt(n-2)-'A')*26*26)%ModSize; } …………

More Related