(Big One) C Language - 09 ฟังก์ชันเรียกตัวเอง4. Introduction
• การเรียกตัวเอง (Recursion) คือการทําซ้ํารูปแบบ
หนึ่ง เหมือนกับการวนรอบ (Loop)
• ข้อดี คือ ในบางโจทย์ปัญหาจะเขียนด้วย Loop
ยากมาก แต่การใช้ Recursion จะง่ายกว่า
• ข้อเสีย คือ Recursion ใช้หน่วยความจํา Stack ของ
ระบบ ซึ่งอาจจะไม่พอใช้งาน เรียกปัญหาลักษณะ
นี้ว่า Stack Overflow
อ. กิตตินันท์ น้1อยมณี 4
6. Factorial
5! = 5 x 4 x 3 x 2 x 1 = 5 x 4!
4! = 4 x 3!
3! = 3 x 2!
2! = 2 x 1!
1! = 1
อ. กิตตินันท์ น้1อยมณี 6
ขั้นตอนที่ 2 : เงื่อนไขการ
หยุดเรียกตัวเอง
ขั้นตอนที่ 1 : สูตรในการ
เรียกตัวเองคือ
n! = n x (n-1)!
24. Factorial
• ดังนั้น Recursion จะดีกว่า Loop ตรงที่มันสามารถ
ทําซ้ําได้โดยการเรียกใช้ตัวมันเองให้ทํางานด้วย
ข้อมูลที่ต่างกันออกไป
• ทําไปเรื่อยๆ จนหมดก็จะได้คําตอบออกมาเอง
อ. กิตตินันท์ น้1อยมณี 24
27. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 27
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
28. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 28
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
เป้าหมายคือย้ายจานทุกจานมาอยู่ที่เสาปลายทางให้หมด โดยเรียงตามขนาด
ของจานในลักษณะเดิม
29. Tower of Hanoi
• โดยพื้นฐานแล้วจะมีเสาอยู่ทั้งหมด 3 ต้น
• และมีจานสวมเสาเหล่านี้อยู่
• ตามตํานานเล่าว่ามีจํานวนจานอยู่ทั้งหมด 64 จาน
• แต่ในโจทย์ปัญหานี้ลองแค่ 3 ก่อนก็พอ
อ. กิตตินันท์ น้1อยมณี 29
30. Tower of Hanoi
ข้อกําหนดคือ
• เราจะย้ายจากเสาต้นทาง (เสาที่ 1) ไปยังเสา
ปลายทาง (เสาที่ 3)
• โดยมีเสาที่ 2 เป็นเสาพัก
• มีข้อห้ามคือ ห้ามมีจานใหญ่ทับจานเล็ก
อ. กิตตินันท์ น้1อยมณี 30
31. Tower of Hanoi
ขั้นตอนการย้ายมี 3 ขั้นตอนดังนี้
1. ต้องย้ายจานข้างบนไปพักจนเหลือจานเดียว
แล้วค่อยย้ายจานล่างสุดไปไว้ที่ปลายทาง
อ. กิตตินันท์ น้1อยมณี 31
32. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 32
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
33. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 33
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
34. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 34
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
ตรวจดูว่าต้นทางเหลือจานเดียวรึยัง? (ถ้ายังไม่หมดให้ทําจนกว่าจะหมด)
(เสาพัก) (ปลายทาง)
35. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 35
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
ย้ายมาเสาปลายทางไม่ได้
เพราะจาน2 ใหญ่กว่าจาน1
(เสาพัก) (ปลายทาง)
36. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 36
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
37. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 37
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3 จานที่ 2 จานที่ 1
จานที่ออกมาจากต้นทางต้องมาอยู่ที่ปลายทั้งหมด ดังนั้นย้ายจาน 1 อีก
(เสาพัก) (ปลายทาง)
38. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 38
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3 จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
39. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 39
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3 จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
41. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 41
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
42. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 42
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
43. Tower of Hanoi
ขั้นตอนการย้ายมี 3 ขั้นตอนดังนี้
3. เป้าหมายครั้งนี้คือจะต้องย้ายจานจากเสาพัก
ทั้งหมดไปยังเสาปลายทางให้ได้ ซึ่งขั้นตอนคือ
(เป็นการเรียกงานย่อยๆ ออกมา หรือเป็น
Recursion นั่นเอง)
อ. กิตตินันท์ น้1อยมณี 43
44. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 44
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
45. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 45
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
46. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 46
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
47. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 47
เสาที่ 1 เสาที่ 2 เสาที่ 3
(ต้นทาง)
จานที่ 3
จานที่ 2
จานที่ 1
(เสาพัก) (ปลายทาง)
48. Tower of Hanoi
ถ้ามี 1 จาน ย้าย 1 ครั้ง (Hanoi 1 Dish: H(1) = 1)
ถ้ามี 2 จาน ย้าย 3 ครั้ง (Hanoi 2 Dish: H(2) = 2H(1) +1)
ถ้ามี 3 จาน ย้าย 7 ครั้ง (Hanoi 3 Dish: H(3) = 2H(2) +1)
ถ้ามี 4 จาน ย้าย 15 ครั้ง (Hanoi 4 Dish: H(4) = 2H(3) +1)
ถ้ามี 5 จาน ย้าย 31 ครั้ง (Hanoi 5 Dish: H(5) = 2H(4) +1)
อ. กิตตินันท์ น้1อยมณี 48
เงื่อนไขการหยุด
สูตรในการ
เรียกตัวเอง
คือ
H(n) = 2H(n-1)+1
หมายเหตุ: เทคนิคคือพยายามหาความสัมพันธ์ของจานก่อน
หน้ากับจานปัจจุบันให้ได้
49. Tower of Hanoi
• พูดไปก็ไม่เห็นภาพ (ไม่เห็น Code)
• ดังนั้นลองมาดู Pseudo Code กัน
อ. กิตตินันท์ น้1อยมณี 49
50. Tower of Hanoi
Algorithm TowerHanoi( m:integer, i:integer, j:integer )
{ m = จํานวนจาน, i = เสาต้นทาง, j = เสาปลายทาง }
{ m >= 1, 1 <= i <= 3, 1 <= j <= 3 }
If m > 0 then
k := 6 – i – j
TowerHanoi( m – 1, i, k )
Print “Disc m from i to j”
TowerHanoi( m – 1, k, j )
End If
End Algorithm
อ. กิตตินันท์ น้1อยมณี 50
52. Tower of Hanoi
• m คือ จํานวนจาน
• i คือ เสาต้นทาง
• j คือ เสาปลายทาง
• k คือ เสาพัก หาได้จาก 6-i-j
อ. กิตตินันท์ น้1อยมณี 52
หมายเหตุ: เลข 6 เกิดจากการเอาจํานวนเสาทั้งหมดลบด้วยเสาต้นทางและเสา
ปลายทาง
53. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 53
ย้ายจากเสาต้นทางไปยังเสาพัก (ขั้นตอนที่ 1)
55. Tower of Hanoi
อ. กิตตินันท์ น้1อยมณี 55
ย้ายเสาพักไปไว้ที่เสาปลายทาง (ขั้นตอนที่ 3)
57. Tower of Hanoi
• ยังมีอีกหลายโจทย์ที่ใช้ Recursion
• เป็นอีกหนึ่งทางเลือกที่น่าสนใจ
• มักใช้ในกรณีที่ไม่ต้องการเขียน Loop หรือเขียน
Loop ลําบาก ก็สามารถเอา Recursion มา
แก้ปัญหาได้
อ. กิตตินันท์ น้1อยมณี 57
58. Tower of Hanoi
• ดังนั้นนับจากนี้ไป หากมีการวนรอบเกิดขึ้น เรา
ต้องมาคิดก่อนว่าจะใช้ Loop ดี หรือว่าใช้
Recursion ดี
อ. กิตตินันท์ น้1อยมณี 58