1 / 32

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

lynda
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. 第一章 學習重點 • 多多學習各種視野的演算法(Algorithms),有助於提昇程式設計功力。 • 本書從第2章起將分別說明各個領域的典型演算法。 • 本章將說明與這些領域較為不同的簡單之演算法,以奠定演算法的基礎。

  3. 1-0 何謂演算法 • 演算法(algorithms)是指解決問題的邏輯或步驟。解決問題的演算法有很多種,但是適合人類使用的演算法卻不見得(說一定也不為過)不會成為電腦適用的演算法。

  4. 1-0 何謂演算法 • 演算法的評價 • 1.信賴度高 • 2.處理效率佳 • 3.具普遍性 • 4.具擴充性 • 5.一目了然 • 6.可移植性(Portability)高

  5. 1-0 何謂演算法 • 演算法與資料結構 • 電算處理通常會處理到大量的資料,而資料結構(data structure)如有不同,則其演算法便會不同。 • 正如『Algorithms +Data Structure=Program(演算法+資料結構=程式)』(N.Wirth著)這個書名,資料結構與演算法具有緊密的關係,選取好的資料結構,就能製作出好的程式。

  6. 1-1 漸進式-排列組合 • 開始練習演算法的邏輯推演… • 例題1 求解 • 求由n個之中選出r個數字排列組合的數值

  7. 1-1 漸進式-排列組合 • 變成Java程式 • class Rei01Panel extends Panel { • long combi(int n,int r) { • int i; • long p=1; • for (i=1;i<=r;i++) • p=p*(n-i+1)/i; • return p; • } • public void paint(Graphics g) { • int n,r; • for (n=0;n<=5;n++){ • for (r=0;r<=n;r++) • g.drawString(""+n+"C"+r+"="+combi(n,r),r*60,n*20+20); • } • } • } • …

  8. 1-2 映射 • 例題2 直方圖(histogram) • 將0~100的得分按每10分分成一組(0~9,10~19,...90~99,100共11組),求各組的分數分佈(histogram) histo[0]~histo[10]為求分數的陣列,histo[0]存放0~9的分數histo[1]存放10~19的分數,依次類推。

  9. 1-2 映射 • 以35分為例,將此分數除以10(分數分佈的幅度)的商數的3之histo[3]的內容+1,分數的分佈即可計算出來。 • 由此我們就可將下列的0~100分的資料範圍映射成0~10的範圍。

  10. 1-2 映射 • class Rei02Panel extends Panel { • public void paint(Graphics g) { • final int Num=20; • int[] a={35,25,56,78,43,66,71,73,80,90, • 0,73,35,65,100,78,80,85,35,50}; • int[] histo=new int[11]; • int i,rank; • for (i=0;i<=10;i++) • histo[i]=0; • for (i=0;i<Num;i++) { • rank=a[i]/10; // 映射 • if (0<=rank && rank<=10) • histo[rank]++; • } • for (i=0;i<=10;i++) { • g.drawString(""+i*10+" - :",10,i*20+20); • g.drawString(""+histo[i],50,i*20+20); • } • } • }

  11. 1-3 排名 • 例題3 單純的方法假設有成績測驗分數的資料,現欲求其排名順序 • 假設有下列的得分資料:

  12. 1-3 排名 • class Rei03Panel extends Panel { • public void paint(Graphics g) { • final int Num=10; • int[] a={56,25,67,88,100,61,55,67,76,56}; • int[] juni=new int[Num]; • int i,j; • for (i=0;i<Num;i++) { • juni[i]=1; • for (j=0;j<Num;j++) { • if (a[j]>a[i]) • juni[i]++; • } • } • g.drawString("得分 排名",10,20); • for (i=0;i<Num;i++) { • g.drawString(""+a[i],10,i*20+40); • g.drawString(""+juni[i],50,i*20+40); • } • } • }

  13. 1-3 排名—改良 • 在例題3的排名順序演算法中,資料如為n個,反覆計算次數便為n2,因此資料如有增加,資料的處理時間變化增加。為此我們要想出減低反覆計算次數的排名順序演算法來 • 當我們將分數範圍設定為0~100時,需將此分數範圍增加。我們要設定juni[0]~juni[100]的陣列,並額外設定1個juni[101]的陣列,此2陣列的內容設定為0。

  14. 1-3 排名—改良 • 將下來將101的元素的初始值設定為1(表示排名順序為1),再將1各右邊的元素內容加在juni[100]→juni[0]的各陣列內。 • 如此就可求出〈得分+1〉的陣列順序了。以上例而言,100分的排名是在101的位置上,88分的排名是在89的位置上。 • 這個方法的資料如為n,資料範圍如為m,則排名順序反覆計算次數為n+m次。

  15. 1-3 排名—改良 • public void paint(Graphics g) { • final int Num=10,Max=100,Min=0; • int[] a={56,25,67,88,100,61,55,67,76,56}; • int[] juni=new int[Max+2]; • int i; • for (i=Min;i<=Max;i++) • juni[i]=0; • for (i=0;i<Num;i++) • juni[a[i]]++; • juni[Max+1]=1; • for (i=Max;i>=Min;i--) • juni[i]=juni[i]+juni[i+1]; • g.drawString("得分 排名",10,20); • for (i=0;i<Num;i++) { • g.drawString(""+a[i],10,i*20+40); • g.drawString(""+juni[a[i]+1],50,i*20+40); • } • }

  16. 1-4 亂數排列 • 例題4 亂數排列(效率較差的方法)以1~N的值產生亂數排列 • 以1~6為例,其亂數排列為3,2,5,1,6,4。 • 下列的演算法在做差的情況下是以的次序反覆進行計算,因此是效率差的方法。 • (1)求得1個1~的亂數。將此亂數設為排列的第1個資料。 • (2)將其下以-1次反覆計算 • (3)求得1個~1的亂數 • (4)(3)所求得的亂數如以代入目前所產生的排列中,則返回(3)。

  17. 1-4 亂數排列 • public void paint(Graphics g) { • final int N=20; • int[] a=new int[N+1]; • int i,j,flag; • a[1]=irnd(N); • for (i=2;i<=N;i++) { • do { • a[i]=irnd(N); • flag=0; • for (j=1;j<i;j++) • if (a[i]==a[j]) { • flag=1;break; • } • } while (flag==1); • } • String s=""; • for (i=1;i<=N;i++) • s=s+a[i]+","; • g.drawString(s,10,20); • }

  18. 1-4 亂數排列—改良

  19. 1-4 亂數排列—改良 • public void paint(Graphics g) { • final int N=20; • int[] a=new int[N+1]; • int i,j,d; • for (i=1;i<=N;i++) • a[i]=i; • for (i=N;i>1;i--) { • j=irnd(i-1); • d=a[i];a[i]=a[j];a[j]=d; • } • String s=""; • for (i=1;i<=N;i++) • s=s+a[i]+","; • g.drawString(s,10,20); • }

  20. 1-5 蒙地卡羅法 • 例題5 求π以蒙地卡羅法求π的值

  21. 1-5 蒙地卡羅法 • …. • add(p=new Panel(),"Center"); • add(tf=new TextField("",10),"North"); • add(bt=new Button("圓周率的計算"),"South"); • bt.addActionListener(new ActionListener() { • public void actionPerformed(ActionEvent e) { • Graphics g=p.getGraphics(); • final int N=50000; • double x,y,pai; • int i,sum=0,px,py; • g.clearRect(50,10,100,100); • g.drawRect(50,10,100,100); • for (i=1;i<N;i++) { • x=Math.random(); • y=Math.random(); • if (x*x+y*y<1) { • px=50+(int)(100*x);py=110-(int)(100*y); • g.drawLine(px,py,px,py); • sum++; • } • } • pai=(double)4*sum/N; • tf.setText("圓周率="+pai); • g.dispose(); • …

  22. 1-5 蒙地卡羅法—求面積 • 練習問題5 求面積以蒙地卡羅法求出橢圓的面積 將0~2的亂數對應至,0~1的亂數對應至,並將其均勻的分佈在的長方形內。若將分佈在1/4橢圓(圖的斜線部分)內的亂數數量設為,分佈在亂數的總數設為,1/4橢圓的面積設為,則, 橢圓的面積則為:

  23. 1-5 蒙地卡羅法—求面積 • public void actionPerformed(ActionEvent e) { • Graphics g=p.getGraphics(); • final int N=50000; • double x,y,s; • int i,sum=0,px,py; • g.clearRect(50,10,100,100); • g.drawRect(50,10,100,100); • for (i=1;i<N;i++) { • x=2*Math.random(); • y=Math.random(); • if (x*x/4+y*y<=1) { • px=50+(int)(50*x);py=110-(int)(50*y); • g.drawLine(px,py,px,py); • sum++; • } • } • s=(double)4*(2.0*sum/N); • tf.setText("面積="+s); • g.dispose(); • }

  24. 1-6 歐基理德輾轉相除法 • 例題6 歐基理德輾轉相除法(之一)以歐基理德輾轉相除法求出m, n這2個整數的最大公約數 24與18的最大公約數是以下列的方式求出: 2)24 18 3)12 9 4 3

  25. 1-6 歐基理德輾轉相除法(1) • 這個方法是根據「設有整數,的最大公約數可轉換成求的最大公約數的方法」的原理而來的。 • 也就是說,m與n的大問題可轉換成的m-n與n小問題,而也可以對m-n用同樣方式反覆處理下去,當m=n時,m(或n)就為所要求出的最大公約數。 • 此方法可整理成如下的演算法:(1)當m不等於n時,反覆進行下列的運算(2)若m>n則m=m-n 否則 n=n-m(3) m(或n)為所要求出的最大公約數。 • m=24, n=18時,將m與n的值描繪出的圖形如下所示:

  26. 1-6 歐基理德輾轉相除法(1) • public void actionPerformed(ActionEvent e) { • int m,n; • m=Integer.parseInt(tf1.getText()); • n=Integer.parseInt(tf2.getText()); • while (m!=n) { • if (m>n) • m=m-n; • else • n=n-m; • } • tf3.setText("最大公約數="+m); • }

  27. 1-6 歐基理德輾轉相除法(2) • m與n的差如相差太大時,可用(m % n)來取代(m-n),這樣的處理效率較高。以下便以此方法求出最大公約數。 • m%n歐基理德輾轉相除演算法解說如下:(1)設k為m除n以後的餘數(2)將n代入m,k代入n(3)k如不等於0則返回(1)(4)m即為所要求得的最大公約數。

  28. 1-6 歐基理德輾轉相除法(2) 假設m=32, n=14時: m n k 32 14 4 (32%14=4) 14 4 2 (14%4=2) 4 2 0 ←結束條件 2 0 ↑ 答案

  29. 1-6 歐基理德輾轉相除法(2) • public void actionPerformed(ActionEvent e) { • int m,n,k; • m=Integer.parseInt(tf1.getText()); • n=Integer.parseInt(tf2.getText()); • do { • k=m % n; • m=n;n=k; • } while(k!=0); • tf3.setText("最大公約數="+m); • }

  30. 1-7 厄拉多塞篩的求質數法 • 例題7 質數的判定,判斷n是否為質數 • 質數是指除了1及其本身以外沒有其他約數的數,2,3,5,7,11...等都是質數。1並不是質數。在判斷n是否為質數時,將n除n以以下的整數直至2為止,以觀察能否除盡,這時如有被除盡的數,便被視為質數而脫離出迴圈。到了最後如無除盡的數,則此數即為質數。此外,即使以n/2以上的整數除以n,n也沒有被除盡的道理,因此程式開始時的值並不是從n開始,從n/2開始也沒關係,這點從直覺上即可判斷出來。 • 在數學計算上也可從 開始。

  31. 1-7 厄拉多塞篩的求質數法 • public void actionPerformed(ActionEvent e) { • int i,n,Limit; • n=Integer.parseInt(tf.getText()); • if (n>=2) { • Limit=(int)Math.sqrt(n); • for (i=Limit;i>1;i--) { • if (n%i ==0) • break; • } • if (i==1) • ta.setText(ta.getText()+n+"是質數\n"); • else • ta.setText(ta.getText()+n+"不是質數\n"); • } • }

  32. 1-7 厄拉多塞篩的求質數法 • 厄拉多塞篩演算法解說如下:1.將2~n的所有數存放至「篩子」。2.將「篩子」中最小的數設為質數。3.從「篩子」中取出質數的所有倍數4.在達到n之前,反覆進行(2)~(3),留在「篩子」(沒有劃斜線的部分)數即為質數。

More Related