400 likes | 591 Views
Algorithmics. The discipline of algorithms. Abu Ja ’ far Mohammed ibn Musa al Khowarizmi. Algorithm comes from the name of a Persian, Abu Ja ’ far Mohammed ibn Musa al Khowarizmi (c. 825 A. D.). al-Khwarizmi.
E N D
Algorithmics The discipline of algorithms
Abu Ja’far Mohammed ibn Musa al Khowarizmi • Algorithm comes from the name of a Persian, Abu Ja’far Mohammed ibn Musa al Khowarizmi (c. 825 A. D.).
al-Khwarizmi • 演算法(algorithm)名稱來自於”al-Khwarizmi”,這是一個約在西元780年出生於伊拉克( Iraq )巴格達( Baghdad )城的阿拉伯數學家阿爾‧可瓦里茲米(Abu Jafar Muhammad ibn Musa al-Khwarizmi)名字的最後一部份,此數學家將印度所發明的十進位數字記號傳入阿拉伯地區(稍後傳入歐洲並成為現今我們使用的數字記號),並且著有一本名為”ilm al jabr w’al-muqabala”的書籍,此書有系統地討論一元二次方程的解法,啟發了代數學的發展。此書在12世紀被翻譯為拉丁文,名為Algebra et Almucabala, (Algebra源自阿拉伯書名中之al jabr),而成為代數學(Algebra)一字的由來。
What is an algorithm (1/2) • Any special method of solving a certain kind of problem -- Webster’s • A precise method useable by a computer for the solution of a problem. -- Viewed by Computer Engineers • In mathematics and computing, an algorithm is a procedure (a finite set of well-defined instructions) for accomplishing some task which, given an initial state, will terminate in a defined end-state. -- WiKipedia
What is an algorithm (2/2) • An algorithm is composed of a set of steps for solving a specific problem. It should satisfy the following properties: • Zero or more inputs • At least one output • Finiteness (the number of steps should be finite and the execution of the steps should terminate) • Definiteness (to compute 5/0 is not definite) • Effectiveness (to compute √2 as an infinite decimal is not effective)
A recipe is an algorithm • Informally, the concept of an algorithm is often illustrated by the example of a recipe. • 梅焗肉排材料:(4人份)一字排12兩鹹話梅6-8粒紅椒2隻中國芹菜2條洋蔥1小個紅谷米少許冰糖適量生抽適量 • 做法:1. 話梅連一隻切角紅椒和紅谷米以六碗水煎至一碗水,隔渣保留汁及話梅備用。中國芹菜切段;洋蔥及另一隻紅椒切角,備用。2. 一字排洗淨,切件,加適量生粉拌勻,放滾油內炸至金黃香脆,瀝乾油備用。3. 取話梅及汁,加入生抽、冰糖煮滾,再加中國芹菜、紅椒角、洋蔥略煮約1分鐘,放一字排燜焗約2分鐘至入味,埋少許生粉水即可。
A program is an algorithm • import javax.swing.*; • public class EuclidGCDApplet extends JApplet{ • public void init( ){ • int 整數m,整數n,最大公因數; • String 輸入字串1,輸入字串2,顯示字串; • 輸入字串1=JOptionPane.showInputDialog("請輸入正整數m?"); • 輸入字串2=JOptionPane.showInputDialog("請輸入正整數n?"); • 整數m=Integer.parseInt(輸入字串1); • 整數n=Integer.parseInt(輸入字串2); • 最大公因數=EuclidGCD(整數m, 整數n); • 顯示字串="整數"+整數m+"與整數"+整數n+"的最大公因數為"+最大公因數; • JOptionPane.showMessageDialog(null,顯示字串); • } //方法:init() 定義區塊結束
Representation of Algorithms • 一般我們使用自然語言(中文或英文等語言)、流程圖(flow chart)、虛擬碼(pseudo code)或高階程式語言(high level programming language)來表示演算法。 • 例如,以下的例子使用自然語言(中文與英文)描述一個古老的演算法 歐幾里德(Euclid)GCD演算法。 • 歐幾里德(Euclid)GCD演算法大約在西元前300年由希臘數學家歐幾里德提出,可用於求出二個整數的最大公因數(GCD, Greatest Common Divisor)。
Pseudo Code • 虛擬碼以一種混雜著自然語言與高階程式語言結構的方式來描述演算法,試圖達到簡潔易讀、容易分析,而且也容易轉換為高階程式語言的目的。 • 以下介紹Goodrich及Tamassia在「Data Structures and Algorithms in JAVA」一書中所提出的虛擬碼格式:
Pseudo Code • 宣告:以 Algorithm 方法名稱(參數1,參數2,…):來宣告一個演算法並指明其參數。例如,Algorithm Euclid-GCD(m, n): 表示我們要定義一個具有兩個參數m及n而名稱為Euclid-GCD的演算法,。 • 設定動作:以 ← 表示,用以將一個算式之值存入某一個變數中。例如,m←3+8 表示要將3+8的值存入變數m中。 • 相等比較:以 = 表示,可以比較二個算式是否等值。例如,m=3+8 表示要比較3+8的值是否與變數m的值相等。
Pseudo Code • 決策結構:以 if條件then條件為真的動作 else 條件為偽的動作 來表示,並以縮排來表示所有包含在條件為真的動作及條件為偽的動作中的所有指令。例如, • if m=3+8 then b←3+8else c←3+8 表示當變數m的值與3+8相等時,會執行將3+8的值存入變數b的動作,否則即執行將3+8的值存入變數c的動作。
Pseudo Code • while迴圈:以 while條件do迴圈指令 來表示,並以縮排來表示所有包含在迴圈中的所有指令。當條件成立時,會持續執行所有包含在迴圈中的指令。例如, • while m=3+8 do b←3+8 c←3+8 表示當變數m的值與3+8相等時,會持續執行將3+8的值存入變數b與將3+8的值存入變數c的動作。
Pseudo Code • repeat迴圈:以 repeat迴圈指令 until條件 來表示,並以縮排來表示所有包含在迴圈中的所有指令。此虛擬碼會持續執行所有包含在迴圈值中的指令,直到條件成立為止。例如, • repeat b←3+8 c←3+8until m=3+8 表示會持續執行將3+8的值存入變數b與將3+8的值存入變數c的動作,直到變數m的值與3+8相等為止。
Pseudo Code • for迴圈:以 for迴圈範圍及變動 do 迴圈指令 來表示,並以縮排來表示所有包含在迴圈中的所有指令。例如, • for i←3 to 8 do b←3+8 c←3+8 表示在變數i的值由3到8(即i為3、4、5、6、7、8)的情況下,會持續執行將3+8的值存入變數b與將3+8的值存入變數c的動作。
Pseudo Code • 陣列元素索引:以 A[i] 代表陣列A中註標(index)為i的元素,一個有n個元素的陣列,其元素註標為0,1,…,n-1。例如,A[5] 表示陣列A中註標為5的元素。 • 方法呼叫:以 物件.方法(參數…) 來代表。注意,當物件是明確的時候,物件可以省略不寫。例如,Math.random() 表示要呼叫Math物件無參數的random()方法。 • 方法返回:以 return 方法返回值 來代表。例如,return 3+8 表示要傳回3+8之值。
Java Method for Euclid Alg. • 使用虛擬碼表示演算法可以方便演算法的分析,增加演算法的易讀性,並且可以方便的將演算法轉變成可以直接在電腦上執行的程式語言程式碼。例如,以下為將以虛擬碼表示的歐幾里德演算法轉換為Java語言程式碼的例子: int Euclid_GCD(int m, int n) { int r=m%n; while (r!=0) { m=n; n=r; r=m%n; } return n; }
Java Applet for Euclid Alg. 範例程式(檔名:EuclidGCDApplet.java) • //檔名:EuclidGCDApplet.java • //說明:此程式可輸入二個整數,並以歐幾里得GCD演算法求其最大公因數(GCD) • import javax.swing.*; • public class EuclidGCDApplet extends JApplet{ • public void init( ){ • int 整數m,整數n,最大公因數; • String 輸入字串1,輸入字串2,顯示字串; • 輸入字串1=JOptionPane.showInputDialog("請輸入正整數m?");
Java Applet for Euclid Alg. • 輸入字串2=JOptionPane.showInputDialog("請輸入正整數n?"); • 整數m=Integer.parseInt(輸入字串1); • 整數n=Integer.parseInt(輸入字串2); • 最大公因數=EuclidGCD(整數m, 整數n); • 顯示字串="整數"+整數m+"與整數"+整數n+"的最大公因數為"+最大公因數; • JOptionPane.showMessageDialog(null,顯示字串); • } //方法:init() 定義區塊結束
Java Applet for Euclid Alg. • static int EuclidGCD(int m, int n) { • int r=m%n; • while (r!=0) { • m=n; • n=r; • r=m%n; • } • return n; • } //方法:EuclidGCD() 定義區塊結束 • } //類別:EuclidGCDApplet 定義區塊結束
Java Applet for Euclid Alg. 網頁檔案(檔名:EuclidGCDApplet.html) • <html> • <h1>EuclidGCDApplet執行中<h1> • <applet code="EuclidGCDApplet.class" width=350 height=100> • </applet> • </html> 執行結果(以瀏覽器載入檔案:EuclidGCDApplet.html)
Correctness and Efficiency • 設計一個演算法,首先要考慮的就是正確性(correctness),也就是演算法是否能產生正確的結果,在達到正確性的要求之後,我們就要特別考慮演算法的效能(efficiency)了,也就是要考慮演算法是否能夠有效率的的執行。一般而言,若是數個演算法均能夠產生相同且正確的結果,則我們大都以有效性來衡量其優劣。
An Alg. for Testing Primes • 我們可以看出,輸入大於2的任意正整數n,若n是質數,則演算法Prime1需要執行整數除法求餘數(n%i)動作與整數比較((n%i)=0)動作n-2次之後,才可以知道n是質數。另外,若n不是質值,則演算法Prime1只要執行整數除法求餘數與整數比較動作1次,就可以知道n不是質數了。
Hint • 每個整數n的因數都是成對出現的,例如,16的因數為1與16(1*16=16)、2與8(2*8=16)、4與4(4*4=16)。成對出現的因數中,一個會小於等於n的平方根,而另一個則是大於等於n的平方根,因此,我們只要檢查小於等於n的平方根的所有不等於1的整數中是否有n的因數就可以知道n是不是質數了。
The Other Alg. for Testing Primes • 我們根據上列的定理設計出另一個演算法Prime2:
Prime1Applet 範例程式(檔名:Prime1Applet.java) • //檔名:Prime1Applet.java • //說明:此程式可輸入一個大於2的整數,並判斷此整數是否為質數(prime number) • import javax.swing.*; • public class Prime1Applet extends JApplet { • public void init(){ • int 整數n; • String 輸入字串,顯示字串; • 輸入字串=JOptionPane.showInputDialog("請輸入大於2的整數n?");
Prime1Applet • 整數n=Integer.parseInt(輸入字串); • boolean 是質數; • long 演算法執行前時間=System.currentTimeMillis(); • 是質數=Prime1(整數n); • long 演算法執行後時間=System.currentTimeMillis(); • long 演算法執行時間=演算法執行後時間-演算法執行前時間; • if(是質數) 顯示字串=整數n+"是質數"; • else 顯示字串=整數n+"不是質數"; • 顯示字串+=("\n演算法執行時間為"+演算法執行時間+"毫秒(milli-seconds)");
Prime1Applet • JOptionPane.showMessageDialog(null,顯示字串); • } //方法:init() 定義區塊結束 • boolean Prime1(int n) { • for (int i=2;i<=n-1;++i) • if (n%i==0) return false; • return true; • } • } //類別:Prime1Applet 定義區塊結束
Prime1Applet 網頁檔案(檔名:Prime1Applet.html) • <html> • <h1>Prime1Applet執行中<h1> • <applet code="Prime1Applet.class" width=350 height=100> • </applet> • </html> 執行結果(以瀏覽器載入檔案:Prime1Applet.html)
Prime2Applet 範例程式(檔名:Prime2Applet.java) • //檔名:Prime2Applet.java • //說明:此程式可輸入一個大於2的整數,並判斷此整數是否為質數(prime number) • import javax.swing.*; • public class Prime2Applet extends JApplet { • public void init(){ • int 整數n; • String 輸入字串,顯示字串; • 輸入字串=JOptionPane.showInputDialog("請輸入大於2的整數n?"); • 整數n=Integer.parseInt(輸入字串);
Prime2Applet • boolean 是質數; • long 演算法執行前時間=System.currentTimeMillis(); • 是質數=Prime2(整數n); • long 演算法執行後時間=System.currentTimeMillis(); • long 演算法執行時間=演算法執行後時間-演算法執行前時間; • if(是質數) 顯示字串=整數n+"是質數"; • else 顯示字串=整數n+"不是質數"; • 顯示字串+=("\n演算法執行時間為"+演算法執行時間+"毫秒(milli-seconds)");
Prime2Applet • JOptionPane.showMessageDialog(null,顯示字串); • } //方法:init() 定義區塊結束 • boolean Prime2(int n) { • for (int i=2;i<=Math.sqrt(n);++i) • if (n%i==0) return false; • return true; • } • } //類別:Prime2Applet 定義區塊結束
Prime2Applet 網頁檔案(檔名:Prime2Applet.html) • <html> • <h1>Prime2Applet執行中<h1> • <applet code="Prime2Applet.class" width=350 height=100> • </applet> • </html> 執行結果(以瀏覽器載入檔案:Prime2Applet.html)
範例程式1-3.質數檢查演算法Prime2於瀏覽器中執行情形。範例程式1-3.質數檢查演算法Prime2於瀏覽器中執行情形。
範例程式1-2.質數檢查演算法Prime1於瀏覽器中執行情形。範例程式1-2.質數檢查演算法Prime1於瀏覽器中執行情形。