Top Banner
台台台台台 台台台台台台台台台台台 台 /一 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, T aiwan. 台台04-23287870 台台04-23108168 台台台台http://www.drmaster.com.tw 台台 Java 台台台台台台台台台 台台台台台 台台 PG20098 台台 台 台台 西 台台 台台台 / 台台台
32

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

Jan 28, 2016

Download

Documents

Lynda

書名 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. - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 台北總公司/台北縣汐止市新台五路一段 112 號 10 樓 A 棟

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

書名 Java 於資料結構與演算法之實習應用

書號  PG20098原著 河西朝雄著譯者 周明憲 /徐堯譯

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

第一章 學習重點 多多學習各種視野的演算法 (Algorithms) ,

有助於提昇程式設計功力。 本書從第 2 章起將分別說明各個領域的典型

演算法。 本章將說明與這些領域較為不同的簡單之演

算法,以奠定演算法的基礎。

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

1-0 何謂演算法 演算法 (algorithms) 是指解決問題的邏輯或

步驟。解決問題的演算法有很多種,但是適合人類使用的演算法卻不見得(說一定也不為過)不會成為電腦適用的演算法。

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

1-0 何謂演算法 演算法的評價

1. 信賴度高 2. 處理效率佳 3. 具普遍性 4. 具擴充性 5. 一目了然 6. 可移植性 (Portability) 高

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

1-0 何謂演算法 演算法與資料結構

電算處理通常會處理到大量的資料,而資料結構 (data structure) 如有不同,則其演算法便會不同。

正如『 Algorithms +Data Structure=Program(演算法+資料結構=程式)』( N.Wirth 著)這個書名,資料結構與演算法具有緊密的關係,選取好的資料結構,就能製作出好的程式。

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

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

rnC

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

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); } } } …

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

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 的分數,依次類推。

histo [0]

分數分佈的陣列

[1] [2] [3] [9] [10]

35 25 56 78 ...43

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

1-2 映射 以 35 分為例,將此分數除以 10 (分數分佈的幅

度)的商數的 3 之 histo[3] 的內容 +1 ,分數的分佈即可計算出來。

由此我們就可將下列的 0 ~ 100 分的資料範圍映射成 0 ~ 10 的範圍。

0~100

X0~10

X

rank=a[i]/10

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

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); } } }

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

1-3 排名 例題 3 單純的方法

假設有成績測驗分數的資料,現欲求其排名順序 假設有下列的得分資料:

juni

1 +1

56 25 67 88 100 55 67 76 56

j

+1 +1 +1 +1

61

i

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

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); } } }

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

1-3 排名—改良 在例題 3 的排名順序演算法中,資料如為 n 個,反覆計算次數便

為 n2 ,因此資料如有增加,資料的處理時間變化增加。為此我們要想出減低反覆計算次數的排名順序演算法來

當我們將分數範圍設定為 0 ~ 100 時,需將此分數範圍增加。我們要設定 juni[0] ~ juni[100] 的陣列,並額外設定 1 個 juni[101]的陣列,此 2 陣列的內容設定為 0 。

0─

0┬

0

25

─0

─0

┬0

55 56 61 67 76

88

0─

100 101

0 0 0 ...0... 0juni

1 2 100 1010

1個額外的陣列

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

1-3 排名—改良 將下來將 101 的元素的初始值設定為 1 (表示排名順序為

1 ),再將 1 各右邊的元素內容加在 juni[100]→juni[0] 的各陣列內。

如此就可求出〈得分 +1 〉的陣列順序了。以上例而言, 100 分的排名是在 101 的位置上, 88 分的排名是在 89 的位置上。

這個方法的資料如為 n ,資料範圍如為 m ,則排名順序反覆計算次數為 n+m 次。76 77 88 89

2

100 101

13 2… 3 … … 2 …34

76分的排名 88分的排名 100分的排名

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

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); } }

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

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) 。

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

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); }

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

1-4 亂數排列—改良

1 2

交換

1 2 3 N

Na[ ] 2 31 N-1

N-1

1 2 j N

交換

確定

1 2 j N-1

交換

確定

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

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); }

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

1-5 蒙地卡羅法 例題 5 求 π

以蒙地卡羅法求 π 的值

X

X

X

X

X

X

X

X X

X

X

X

X

X

X

X

X

X

X

X

X

X

X

X

X

X

XX

X

X

XX

X

X

1

1

Y

X

半徑1的1/4的面積=4

14

1 2

=正方型的面積 111

將亂數產生的x, y值予以描繪出來的圖形

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

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(); …

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

1-5 蒙地卡羅法—求面積 練習問題 5 求面積

以蒙地卡羅法求出橢圓的面積

s

S

2

-1

-2

1

將 0 ~ 2 的亂數對應至, 0 ~ 1 的亂數對應至,並將其均勻的分佈在的長方形內。若將分佈在 1/4 橢圓(圖的斜線部分)內的亂數數量設為,分佈在亂數的總數設為, 1/4 橢圓的面積設為,則,

橢圓的面積則為:

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

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(); }

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

1-6 歐基理德輾轉相除法 例題 6 歐基理德輾轉

相除法(之一)以歐基理德輾轉相除法求出 m, n 這 2 個整數的最大公約數

2)24 18 3)12 9 4 3

24 與 18 的最大公約數是以下列的方式求出:

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

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 的值描繪出的圖形如下所示:

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

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); }

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

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 即為所要求得的最大公約數。

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

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

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

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); }

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

1-7 厄拉多塞篩的求質數法 例題 7  質數的判定,判斷 n 是否為質數

質數是指除了 1 及其本身以外沒有其他約數的數, 2,3,5,7,11...等都是質數。 1 並不是質數。

在判斷 n 是否為質數時,將 n 除 n 以以下的整數直至 2 為止,以觀察能否除盡,這時如有被除盡的數,便被視為質數而脫離出迴圈。到了最後如無除盡的數,則此數即為質數。此外,即使以 n/2 以上的整數除以 n , n 也沒有被除盡的道理,因此程式開始時的值並不是從 n 開始,從 n/2 開始也沒關係,這點從直覺上即可判斷出來。

在數學計算上也可從 開始。

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

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"); } }

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

1-7 厄拉多塞篩的求質數法 厄拉多塞篩演算法解說如下:

1. 將 2 ~ n 的所有數存放至「篩子」。2. 將「篩子」中最小的數設為質數。3. 從「篩子」中取出質數的所有倍數4. 在達到 n 之前,反覆進行 (2) ~ (3) ,留在「篩子」(沒有劃斜線的部分)數即為質數。

2 n3 4 5 6 7 8 9 10 11 12 13 14 15 16

將2~n的所有的數放入篩子

從篩子取出2的倍數

從篩子取出3的倍數