Programming: Space-Time Relation
ขอเริ่มต้น post ของวันนี้ด้วยการขอโทษก่อนละกัน วันนี้ (จริง ๆ เมื่อวานด้วย) ไม่ได้ไปเยี่ยมบัณฑิตจุฬา ฯ ที่ไปซ้อมรับปริญญา เพราะมีเหตุการณ์สำคัญเกิดขึ้นที่บ้าน ที่คนทั่ว ๆ ไปคงเรียกว่าปัญหาครอบครัวหนะ
แล้วก็ ... เตือนกันอีกครั้งนะ ... ถ้าจะดู post เก่า ๆ ให้มันเป็นลำดับดี ๆ ไปดูที่นี่
มันจะมี link มาที่หน้าของแต่ละ post ใน Tunoblog อันนี้
โปรโมตเสร็จ ก็ขอเข้าเรื่องละกัน คราวนี้จะพูดถึงความสัมพันธ์ระหว่าง ความเร็วของ algorithm กับเนื้อที่ memory ที่จะต้องใช้
สำหรับปัญหาปัญหานึง เราอาจจะมีวิธีแก้หลาย ๆ แบบ ซึ่งสำหรับนักเขียนโปรแกรมเนี่ย เค้ามักถามกันว่า "บิ๊กโอ (Big-O = O ใหญ่น่ะแหละ) เท่าไหร่?"
ใครที่ยังไม่รู้จัก O ตัวนี้ ก็ขอพูดคร่าว ๆ ละกัน
O(g) = { f | f(x) เพิ่มไม่เร็วกว่า g(x) เมื่อ x มีค่ามาก ๆ }
จริง ๆ นิยามแบบชัด ๆ มันก็มีอยู่อะนะ แต่ขี้เกียจยกมา ไปดูเอาเองจาก Wikipedia ละกัน :P
มาต่อกันเรื่องหลัก คราวนี้มาสนใจเรื่อง Space-Time ดีกว่า ...
ทฤษฎีสัมพัทธภาพ
ม่ายช่ายและ :P ... จะพูดถึง Big-O ของเวลา กับ เนื้อที่ memory ที่ algorithm ใช้ตะหาก
Sorting Algorithm
ปัญหาการเรียงข้อมูลเนี่ย เป็นปัญหาสุดคลาสสิก ที่น่าเอามาพูดถึงที่สุด วิธีการเรียงที่นิยมสอนกัน มักจะมีอยู่เท่านี้ (ขาดเกินบ้างนิดหน่อย)
- Selection Sort - ใช้เวลา O(n2) เมื่อมีข้อมูล n ตัว
- Bubble Sort - ใช้เวลา O(n2)
- Insertion Sort - ใช้เวลา O(n2)
- Shell Sort - ใช้เวลา O(n1.5) (จริง ๆ มี O(n log2n) นะ ดูที่นี่)
- Merge Sort - ใช้เวลา O(n log n)
- Quick Sort - ใช้เวลา O(n log n) (เฉลี่ย)
- Heap Sort - ใช้เวลา O(n log n)
- Bucket Sort - ใช้เวลา O(m + n)
- Radix Sort - ใช้เวลา O(n log m)
หนังสือทั่ว ๆ ไป มักจะไม่พูดถึงขนาดของ memory ที่ต้องใช้ เพราะว่า ไม่มีิอันไหนใช้เกิน O(n) ซึ่งเป็นขนาดของ input แต่เราจะลองมองดูซักนิดนะ ว่ามันเป็นยังไง
- Selection Sort - ใช้เนื้อที่เพิ่ม O(1)
- Bubble Sort - ใช้เนื้อที่เพิ่ม O(1)
- Insertion Sort - ใช้เนื้อที่เพิ่ม O(1)
- Shell Sort - ใช้เนื้อที่เพิ่ม O(1)
- Merge Sort - ใช้เนื้อที่เพิ่ม O(n)
- Quick Sort - ใช้เนื้อที่เพิ่ม O(log n) (เฉลี่ย)
- Heap Sort - ใช้เนื้อที่เพิ่ม O(1)
- Bucket Sort - ใช้เนื้อที่เพิ่ม O(m)
- Radix Sort - ใช้เนื้อที่เพิ่ม O(1)
- Selection Sort - ลูป 2 ชั้น และตัวแปรพักข้อมูลสำหรับการสลับ
- Bubble Sort - ลูป 2 ชั้น และตัวแปรพักข้อมูลสำหรับการสลับ
- Insertion Sort - ลูป 2 ชั้น และตัวแปรพักข้อมูลสำหรับการแทรก
- Shell Sort (กรณีเวลา O(n log2n)) - ลูป 3 ชั้น ตัวแปรสำหรับสร้างลำดับ 2 ตัว และตัวแปรพักข้อมูลสำหรับการสลับ หรือ แทรก
- Merge Sort - Recursive 2 ครั้ง ลูป 1 ชั้นที่มีตัวนับ 2 ตัว กับ array พักข้อมูลความยาว n และลูปคัดลอกค่าจาก array พักข้อมูล
- Quick Sort - ลูป 1 ชั้นที่มีตัวนับ 2 ตัว ตัวแปรพักข้อมูลสำหรับการสลับ และ Recursive 2 ครั้ง
- Heap Sort - ลูป 2 ชั้น 2 ลูป และตัวแปรพักข้อมูลสำหรับการแทรก
- Bucket Sort - ลูปกำหนดค่าเริ่มต้น (ใช้เวลา O(m)) ลูปรับ input และลูปแสดง output (ใช้เวลา O(n))
- Radix Sort (ฐาน 2) - ลูป 2 ชั้น ชั้นนอกทำซ้ำ log2m ครั้ง ชั้นในมีตัวนับ 2 ตัว
Dynamic Programming - Fibonacci Function
อันนี้ คิดว่า หลาย ๆ คนคงคุ้นเคยและรู้อยู่แล้ว หน้าตามันก็ประมาณนี้ (ภาษา C ละกัน)
int fib(int n) { return n <= 1 ? 1 : fib(n - 1) + fib(n - 2); }
จะเห็นว่า code สั้นมาก ดังนั้น จากหลักของเรา พอจะเดาได้ว่า น่าจะมีวิธีทำให้มันทำงานเร็วกว่านี้ แต่ code ยาวกว่านี้ หรือมีตัวแปรเพิ่ม
ลองดูก่อน ว่า เขียนโปรแกรมแบบนี้ ใช้เวลาทำงานเท่าไหร่ ... คำตอบค่อนข้างง่ายนะ เวลาก็คือ O(fib(n)) น่ะแหละ (ว่าไปก็คือ O(αn) เมื่อ α = golden ratio น่ะแหละ)
มันกินเวลาน่าดูเลยนะเนี่ย ลองพยายามทำให้มันเร็วขึ้นสิ ... วิธีง่าย ๆ ก็คือ กำหนดตัวแปรเพิ่มเป็น array ความยาว n แล้วก็คิดค่าไล่ตั้งแต่ f(0) ถึง f(n) ไง หยั่งงี้ f(...) ตัวที่เคยคิดแล้ว ก็ไม่ต้องคิดซ้ำ
int fib(int n) { return a[n] > 0 ? a[n] : a[n] = fib(n - 1) + fib(n - 2); }
แล้วกำหนดค่าเริ่มต้นให้ a[0] = 1, a[1] = 1 และ a[อื่น ๆ] = -1
จริง ๆ มันประหยัดเนื้อที่ได้อีกนะ แต่คราวนี้โปรแกรมจะซับซ้อนละ ...
int fib(int n)
{
int f, last1, last2;
if (n <= 1) return 1;
last1 = 1;
last2 = 1;
for (--n; n > 0; --n)
{
f = last1 + last2;
last2 = last1;
last1 = f;
}
return f;
}
จะเห็นว่า เหลือตัวแปรแค่ 3 ตัว (คือ memory O(1)) แลกกับ code ที่ยาวขึ้นอีกนิดนึง
จริง ๆ ยังทำให้มันเร็วกว่านี้ได้อีกแหละ แต่คราวนี้ code จะยาวขึ้นเยอะเลย แล้วจะเร็วขึ้นเฉพาะเมื่อ n เยอะมาก ๆ ๆ ๆ ๆ เท่านั้น
เอาเป็นว่า หยุดแค่นี้ก่อนดีกว่า
3 Comments:
Hey, CUD35 now has a new google group. Please visit ner...
Nirand
group.google.com/cud35
At first I think about how some Einstein confusing theory have something to do with programming. Great article, but the article makes me think if we can solve some f**king slow problem in no time if only we have large enough space. What do you think?
That's almost true.
Post a Comment
<< Home