บทที่ 2 การวิเคราะห์อัลกอริทึม
หัวข้อ การวิเคราะห์อัลกอริทึม การนับจำนวนการทำงานของคำสั่งพื้นฐาน แบบทดลอง และแบบคณิตวิเคราะห์ การนับจำนวนการทำงานของคำสั่งพื้นฐาน อัตราการเติบโตของฟังก์ชัน สัญกรณ์เชิงเส้นกำกับ การวิเคราะห์การทำงาน แบบลำดับ, แบบเลือกทำ, แบบวงวน, แบบเรียกซ้ำ
ขั้นตอนการออกแบบอัลกอริทึม
จุดประสงค์ของการวิเคราะห์อัลกอริทึม เพื่อศึกษาประสิทธิภาพของอัลกอริทึม เวลาการทำงาน ปริมาณหน่วยความจำที่ใช้ในการทำงาน
ประเภทการวิเคราะห์อัลกอริทึม Mathematical Analysis Experimental Analysis แปลงเป็นโค้ด สั่งทำงานกับข้อมูลทดสอบ จับเวลาการทำงาน บันทึกผล วิเคราะห์ความสัมพันธ์ระหว่างเวลาการทำงานกับปริมาณข้อมูล มักเป็นรูปแบบฟังก์ชัน ทางคณิตศาสตร์
SelectionSort selectionSort(d[1..n]){ for (k = n; k > 1; k--) { maxI=1 for (i = 2; i <= k; i++) if (d[i] > d[maxI]) maxI = i d[k]↔d[maxI] }
Selection Sort (ภาษา C) void selectionSort(int d[], int n) { int k, i; for (k = n - 1; k > 0; k--) { int maxI =1; for (i = 0; i <= k; i++) if (d[i]> d[maxI]) maxI = i; int t = d[k]; d[k] = d[maxI]; d[maxI] = t; }
#include <stdio. h> #include <stdlib #include <stdio.h> #include <stdlib.h> #include <windows.h> int main(int argc, char *argv[]) { int i, k, n, repeat = 10; for( n = 0; n<=20000; n+=2000) { int *d = malloc( n * sizeof(int) ); long sum = 0; for (k=0; k<repeat; k++) { for (i=0; i<n; i++) d[i] = i; long start = GetTickCount(); selectionSort(d, n); sum += GetTickCount() - start; } printf("%d \t %f \n", n, (float)sum/repeat); system("PAUSE"); return 0;
Selection Sort (ภาษา Java)
public class TestSelectionSort { public static void main(String[] args) { int repeat = 10; for (int n = 0; n <= 20000; n += 2000) { int[]d = new int[n]; long sum = 0; for (int k = 0; k < repeat; k++) { for (int i = 0; i <n;i++) d[i] = i; { long start = System.currentTimeMillis(); selectionSort(d); sum += System currentTimeMillis() - start; } System.out.printf("%d \t %f \n", (double)sum/repeat);
for (int i = 0; i < 10000; i++) selectionSort(new int[1]); public class TestSelectionSort { public static void main(String[] args) { int repeat = 10; for (int n = 0; n <= 20000; n += 2000) { int[]d = new int[n]; long sum = 0; for (int k = 0; k < repeat; k++) { for (int i = 0; i <n;i++) d[i] = i; { long start = System.currentTimeMillis(); selectionSort(d); sum += System currentTimeMillis() - start; } System.out.printf("%d \t %f \n", (double)sum/repeat); for (int i = 0; i < 10000; i++) selectionSort(new int[1]);
สั่งทำงาน พร้อมบันทึกผล ภาษา C : ใช้ GNU-C Compiler (3.4.2) ภาษา Java : ใช้ Java 6 (build 1.6.0_14-b08) Interpreted-only mode (option –Xint ตอนทำงาน) Compilation to native code (บังคับ compile ด้วยการเรียกเมท็อดว้ำ ๆ สัก 10 000 ครั้ง) Intel Core 2 Duo P8400 2.26Ghz Ram 3GB Windows XP
เปรียบเทียบเวลาการทำงาน 22.1× 10 −6 𝑛 2 2.38× 10 −6 𝑛 2 1.54× 10 −6 𝑛 2
ใช้จำนวนการทำงานของคำสั่งแทนเวลา static int counter= 0; static void selectionSort(int[] d) { counter = 1+d.length +d.length-1; for (int k = d.length-1; k > 0; k--) { int maxI =1; counter += 2 + k+2 + k+1; for (int i = 0; i <= k; i++) { counter += 1; if (d[i] > d[maxI]) { maxI=i; counter+=1; } counter += 3; int t = d[k]; d[k] = d[maxI]; d[maxI] = t;
เขียนโปรแกรมทดลองนับคำสั่ง public class TestSelectionSort { public static void main(String[] args) { int repeat = 10; for (int n = 0; n <= 20000; n += 2000) { int[]d = new int[n]; long sum = 0; for (int k = 0; k < repeat; k++) { for (int i = 0; i <n;i++) d[i] = i;; counter = 0; selectionSort(d); sum += counter; } System.out.printf("%d \t %f \n", n, (double)sum/repeat);
นับจำนวนการทำงานของคำสั่ง
นับเฉพาะคำสั่งตัวแทน static intcounter= 0; static voidselectionSort(int[] d) { for (int k = d.length-1; k > 0; k--) { int maxI =1; for (int i = 0; i <= k; i++) { counter += 1; if (d[i] > d[maxI]) { maxI = i; } int t d[k]; d[k] = d[maxI]; d[maxI]=t;
นับทุกคำสั่ง VS. นับคำสั่งตัวแทน
Mathematical Analysis ไม่ต้องเขียนเป็นโปรแกรม ไม่ต้องสั่งทำงานจริง ไม่ต้องวาดกราฟ วิเคราะห์จาก อัลกอริทึม จะได้เป็นฟังก์ชั่น 1 𝑖=2 𝑘
นับทุกคำสั่ง VS. นับคำสั่งตัวแทน
คำสั่งตัวแทนต้องเป็นคำสั่งพื้นฐาน คำสั่งพื้นฐาน คือคำสั่งที่ ใช้เวลาการทำงานไม่เกินค่าคงที่ค่าหนึ่ง ใช้เวลาการทำงานไม่แปรตามขนาดของ input เช่น + - * / if เปรียบเทียบ return break …
การวิเคราะห์อัลกอริทึม เวลาการทำงาน แปรตามจำนวนการทำงานของคำสั่ง จำนวนการทำงานของคำสั่ง แปรตาม จำนวนการทำงานของ คำสั่งตัวแทน เพื่อความง่าย เราวิเคราะห์อัลกอริทึมเชิงเวลาด้วยการหา ความสัมพันธ์ของ จำนวนการทำงานของคำสั่งตัวแทน ปริมาณข้อมูล
วัดปริมาณข้อมูลขาเข้า พิจารณาว่า ขนาดของ input แปรตามค่าอะไรของ input ตัวอย่าง: sort(d[1…n]) Input เป็นอาเรย์จำนวน n ช่อง แต่ละจำนวนมีค่าจำกัด ดังนั้น n แทนปริมาณข้อมูล ตัวอย่าง:shortestPath( V, E, w, s ) Input เป็นกราฟถ่วงน้ำหนัก ขนาดของกราฟ แปรตามจำนวนปมและจำนวนเส้นเชื่อม ดั้งนั้น |V|+|E| แทนปริมาณของข้อมูล
เปรียบเทียบผลการวิเคราะห์
เปรียบเทียบเวลาการทำงาน
เปรียบเทียบอัตราการเติบโต
อัตราการเติบโต
ทบทวนสูตรคณิตศาสตร์
อัตราการเติบโตของฟังก์ชัน
f(n) vs. g(n) ใครโตเร็วกว่ากัน ให้ดูที่พฤติกรรมตอนที่ค่า n เยอะๆ ว่าใครนำหน้าใคร lim 𝒏→∞ 𝒇 𝒏 𝒈 𝒏 = 𝟎 𝒇 𝒏 โตช้ากว่า 𝒈 𝒏 ∞ 𝒇 𝒏 โตเร็วกว่า 𝒈 𝒏 𝒄 𝒇 𝒏 โตเท่ากัน 𝒈 𝒏 𝒄 คือ ค่าคงตัวที่ไม่ใช่ 0 𝒇 𝒏 ≺𝒈 𝒏 𝒇 𝒏 ≻𝒈 𝒏 𝒇 𝒏 ≍𝒈 𝒏 𝒇 𝒏 โตไม่เร็วกว่า 𝒈 𝒏 𝒇 𝒏 ≼ 𝒈 𝒏 𝒇 𝒏 โตไม่ช้ากว่า 𝒈 𝒏 𝒇 𝒏 ≽ 𝒈 𝒏
ตัวอย่าง 𝒇 𝒏 =𝟏𝟎𝒏, 𝒈 𝒏 = 𝒏 𝟐 𝟏𝟎𝟎𝟎 lim 𝒏→∞ 𝒇 𝒏 𝒈 𝒏 = lim 𝒏→∞ 𝟏𝟎𝒏 𝒏 𝟐 𝟏𝟎𝟎𝟎 = lim 𝒏→∞ 𝟏𝟎𝟎𝟎𝟎 𝒏 = 𝟎 สรุปได้ว่า 𝟏𝟎𝐧 โตช้ากว่า 𝒏 𝟐 𝟏𝟎𝟎𝟎𝟎 ;𝒇 𝒏 ≺𝒈 𝒏
𝒇 𝒏 = 𝟐𝒏 𝟐 −𝟓𝒏, 𝒈 𝒏 = 𝟏𝟎𝒏 𝟐 lim 𝒏→∞ 𝒇 𝒏 𝒈 𝒏 = lim 𝒏→∞ 𝟐𝒏 𝟐 −𝟓𝒏 𝟏𝟎𝒏 𝟐 = lim 𝒏→∞ 𝟐𝒏 𝟐 𝟏𝟎𝒏 𝟐 − 𝟓𝒏 𝟏𝟎𝒏 𝟐 = lim 𝒏→∞ 𝟏 𝟓 − 𝟏 𝟐𝒏 = 𝟏 𝟓 สรุปได้ว่า 𝟐𝒏 𝟐 −𝟓𝒏 โตเท่ากับ 𝟏𝟎𝒏 𝟐 𝒇 𝒏 ≍𝒈 𝒏
L'Hôpital's rule ถ้า 𝒇 𝒏 และ 𝒈 𝒏 เป็นฟังก์ชันที่หาอนุพันธ์ได้ โดย ที่ ถ้า 𝒇 𝒏 และ 𝒈 𝒏 เป็นฟังก์ชันที่หาอนุพันธ์ได้ โดย ที่ lim 𝒏→∞ 𝒇 𝒏 =∞ , lim 𝒏→∞ 𝒈 𝒏 =∞ และหาค่าของ lim 𝒏→∞ 𝒇 ′ 𝒏 𝒈 ′ 𝒏 จะได้ว่า
เรียงลำดับฟังก์ชันตามการเติบโต log 𝑛 5 =5 log 𝑛 𝑛!
สัญกรณ์เชิงเส้นกำกับ
สัญกรณ์เชิงเส้นกำกับ (Asymptotic Notations) little-o little – omega Big – O Big – Omega Big - Theta
little-o
little – omega
Big - Theta
Big – O
Big – Omega
สรุป
Big – O : ขอบเขตบน
Big-Omega : ขอบเขตล่าง
Big – Theta : ขอบเขตกระชับ
จุดประสงค์การใช้สัญกรณ์เชิงเส้นกำกับ เข้าใจพฤติกรรมเมื่อพารามิเตอร์มีค่ามาก วิเคราะห์ได้ง่าย จัดกลุ่มฟังก์ชันตาอัตราการเติบโต
วิเคราะห์ด้วย 𝚶,𝛀,𝚯 จงแสดงว่า
หาอนุพันธ์
ตัวอย่าง log 𝟐 𝒏!
การเขียนฟังก์ชันในรูปของ 𝚶,𝚯 แบบง่ายๆ ผลบวกของพจน์หลายพจน์ เลือกพจน์ที่โตเร็วสุด ข้อสังเกต เช่น
อัตราการเติบโต
การวิเคราะห์อัลกอริทึม การทำงานแบบลำดับ เลือกทำ ทำซ้ำเป็นวงวน ทำซ้ำแบบเรียกซ้ำ
การทำงานแบบลำดับ
การเลือกทำ
การทำงานแบบวงวน
ตัวอย่าง Insertion Sort
ตัวอย่าง while
การทำงานแบบเรียกซ้ำ
ตัวอย่าง การค้นหาแบบทวิภาค
t(m) = t(n/2) + 𝚯(𝟏)
ตัวอย่าง: Tower of Hanoi
dki
ต้นไม้แทนภาระจริงของการเรียกซ้ำ
ขนาดข้อมูล กับ ภาระจริง