การเรียกซ้ำ - มหาวิทยาลัยบูรพา วิทยาเขตจันทบุรี

Download Report

Transcript การเรียกซ้ำ - มหาวิทยาลัยบูรพา วิทยาเขตจันทบุรี

290214 Data Structures and Algorithms
การเรียกซ้า (Recursion)
อ.ธารารัตน์ พวงสุ วรรณ
คณะวิทยาศาสตร์และศิลปศาสตร์
มหาวิทยาลัยบูรพา วิทยาเขตสารสนเทศจันทบุรี
[email protected]
เนือ้ หา



ความแตกต่าง ของ Iterative Solution และ Recursive Solution
การนิยามแบบ Recursion
Recursive Example
Greatest Common Divisor (GCD)
 Fibonacci Numbers
 Towers of Hanoi

Approach to writing Repetition Algorithms
มี 2 Approach คือ
 Use Iteration
 Use Recursion
Recursion is a repetitive process in which an algorithm calls itself
 Some older languages do not support recursion

A Classic Recursive Case


Factorial เป็ น case study
Factorial(n) =
1
if n=0
n x (n-1) x (n-2) x ... x 3 x 2 x 1 if n >0
การหาค่ าแฟกทอเรียล
n! = 1 * 2 * 3 * 4 * ...* n
เช่น
4! = 4 * 3 * 2 * 1
3! = 3 * 2 * 1
2! = 2 * 1
1! = 1
Iterative Factorial Algorithm
Algorithm iterativeFactorial (n)
Calculates the factorial of a number using a loop
Pre n is the number to be raised factoriallly
Post n! is returned
Return factN เป็ นค่ า n!
1
set i to 1
2
set factN to 1
3
loop(i <= n)
1 set factN to factN * i
2 increment i
4
end loop
5
return factN
end iterativeFactorial
Recursive Factorial Algorithm
Algorithm recursiveFactorial (n)
Calculates factorial of a number using recursion
Pre n is the number to be raised factoriallly
Post n! is returned
Return ค่ า n!
1
if (n equal 0)
1 return 1
2
else
1 return (n * recursiveFactorial (n-1))
3
end if
end recursiveFactorial
Recursive Programming
คือ การเขียนโปรแกรมที่ฟังก์ชนั ในโปรแกรมนั้นมีการเรี ยกใช้งาน
ตัวมันเอง (Call itself)
 เรี ยกฟั งก์ชน
ั ที่มีการเรี ยกใช้งานตัวมันเองว่า “Recursive Function”
 บางปั ญหาสามารถที่จะเขียนในรู ปแบบของ recursion จะง่ายกว่า
หลักการแก้ปัญหาในรู ปแบบ recursion
1. นิยามปัญหาในรู ปการเรี ยกตัวเอง
2. มีเงื่อนไขสาหรับจบการทางาน
“One important requirement for a recursive algorithm to be
correct is that it not generate an infinite sequence of call on itself”

ลักษณะของ recursive function
1. call itself directly
2. call itself indirectly หรื อเรี ยกว่า Recursive chains
ตัวอย่างของ Recursive chains
a(formal parameters)
b(formal parameters)
{
{
.
.
.
.
.
.
b(arguments);
a(arguments);
} /* end a */
} /* end b */
“Both a and b are recursive”
ตัวอย่าง
int main(void) {
printf(“The universe is never ending\n”);
main();
return 0;
} //an infinite sequence of call on itself
การคานวณหาค่าแฟกทอเรี ยลของจานวนเต็มบวก
การนิยามแบบ iterative
n! = n * (n-1) * (n-2) * ... 1
อาจเขียนคาจากัดความของฟังก์ชนั ได้วา่
n! = 1 if n ==0
n! = n * (n-1) * (n-2) * ... * 1
if n > 0
Iterative programming
//Function for calculating factorial of integer
long int fact(int n)
{
int x;
prod = 1;
for(x = n; x > 0; x--)
prod = prod * x;
return(prod);
}
การนิยามแบบ Recursion
1. เขียนปัญหาในรู ปการเรี ยกตัวเอง
n! = n * (n-1)!
อาจเขียนคาจากัดความของฟังก์ชนั ได้วา่
n! = 1 if n ==0
n! = n * (n-1)! if n > 0
2. หาเงื่อนไขสาหรับจบการทางาน
คือ เมื่อเรี ยกตัวเองจนถึง 0! = 1
Recursive programming
//Function for calculating factorial of integer
long int fact(int n)
{
if(n == 0) //condition for end calling itself
return(1)
else
Recursion
return(n * fact(n-1));
}
Recursive programming
“Recursive function จะทางานในลาดับที่กลับกันกับเวลาเรียกใช้ ”
จากโปรแกรมหาค่าแฟกทอเรี ยลแบบ recursion การเรี ยกใช้จะเป็ นลาดับดังนี้
n! = n * (n-1)!
(n-1)! = (n-1) * (n-2)!
(n-2)! = (n-2) * (n-3)!
.........
2! = 2 * 1!
1! = 1 * 0!
0! = 1
Recursive programming
ค่าที่ส่งกลับมาจะเป็ นลาดับที่กลับกัน ดังนี้
0! = 1
1! = 1 * 0! = 1
2! = 2 * 1! = 2 * 1 = 2
3! = 3 * 2! = 3 * 2 = 6
4! = 4 * 3! = 4 * 6 = 24
........
n! = n * (n-1)! = ......
Recursive programming
ดังนั้น ส่ ง 4 เข้าไปให้ฟังก์ชนั พอเรี ยกฟังก์ชนั จะได้
return(4 *
return(3 *
return(2 *
return(1 *
return(1);
จะเห็นว่า ค่าส่ งกลับจะเป็ น return(4*3*2*1*1)
Recursive Example

เป็ นตัวอย่างของการแก้ปัญหาแบบ Recursion
 Greatest Common Divisor (GCD)
 Fibonacci Numbers
 Towers of Hanoi
Greatest Common Division(GCD)





เป็ นฟังก์ชนั ทางคณิ ตศาสตร์ ที่รู้จกั กันว่า การหาตัวหารร่ วมมาก
(ห.ร.ม.)
gcd ของจานวนเต็มซึ่งไม่เป็ น 0 พร้อมกัน คือจานวนเต็มที่มากที่สุด
ที่หารทั้งสองจานวนลงตัว
เช่น gcd ของ 10 กับ 25 คือ 5
มีประโยชน์ในการทาเศษส่ วนให้เป็ นเศษส่ วนอย่างต่า
ใช้ Euclidean Algorithm ในการหา gcd ของจานวนเต็มที่ไม่เป็ นค่า
ลบ
Greatest Common Division(GCD)

gcd (a,b) =
a
b
gcd (b, a mod b)
if b = 0
if a = 0
otherwise
Greatest Common Division(GCD)
Algorithm gcd (a, b)
Calculates greatest common division using the Euclidean algorithm
Pre a and b are positive integers greater than 0
Post greatest common divisor returned
Return greatest common divisor returned
...............................................
.................................................
.................................................
..................................................
..................................................
.................................................
end gcd
การหา Fibonacci numbers

การหาชุดของ Fabonacci series จะต้องทราบตัวเลข 2 ตัวแรก
นิยาม
Fib(n) = n
if n = 0 or n = 1
Fib(n) = Fib(n-1) + Fib(n-2) if n > 1
Fibonacci numbers
เขียนเป็ น recursive function ได้วา่
int fib(int n) {
int x,y;
if(n<= 1)
return(n);
x = fib(n-1);
y = fib(n-2);
return(x+y);
}
Tower of Hanoi Problem
A
B
C
เป้ าหมาย
ต้องการเคลื่อนย้าย disk ทั้งหมดไปไว้อีก peg หนึ่ง
ข้ อกาหนด
- เคลื่อนย้ายครั้งละ 1 disk เท่านั้นโดยเคลื่อนย้ายจาก disk บนสุ ดก่อน
- ไม่อนุญาตให้ disk ที่ใหญ่กว่าซ้อนบน disk ที่เล็กกว่า
จากรู ปดังกล่าว หากเราต้องการเคลื่อนย้าย disk ทั้งหมดจาก A ไป C
Recursive solution for Towers of Hanoi Problem
1. if n==1, move the single disk from A to C and stop
2. Move the top n-1 disks from A to B, using C as auxiliary
3. Move the remaining disk from A to C
4. Move the n-1 disks from B to C, using A as auxiliary
A
B
C
A
B
C
A
B
C
A
B
C
Efficiency of recursion
โดยทัว่ ไป โปรแกรมที่มีลกั ษณะ nonrecursive การประมวลผลจะมี
มีประสิ ทธิภาพดีกว่าโปรแกรมที่มีลกั ษณะ recursive ในด้านของเวลาและพื้นที่
หน่วยความจา (space) แต่ลกั ษณะบางโปรแกรมก็เหมาะที่จะเขียนแบบ recursive
เพราะจะทาให้ง่ายกว่าและเกิดข้อผิดพลาดได้นอ้ ยกว่าแบบ nonrecursive
ข้ อดีของ recursive programming
- เขียนได้ส้ นั ง่าย
- มองเห็นแนวทางการแก้ปัญหาได้ชดั เจน
- ใช้เวลาไม่มากในการเขียนโปรแกรม
ข้ อเสี ยของ recursive programming
บางปัญหาไม่เหมาะที่จะแก้ปัญหาด้วย recursive programming เนื่อง
จากทาให้มีการทางานที่ซ้ าซ้อน
เช่น การหา Fibonacci number
Fib(n) = n
if n = 0 or n = 1
Fib(n) = Fib(n-1) + Fib(n-2) if n > 1
ตัวอย่าง
Fib(5) = Fib(4) + Fib(3)
Fib(4) = Fib(3) + Fib(2)
Fib(3) = Fib(2) + Fib(1)
Fib(2) = Fib(1) + Fib(0)