- Có thể thay vòng lặp bằng đệ quy.. 12.2 Nội dung Bất cứ một hàm nào đó có thể triệu gọi hàm khác, nhưng ở đây một hàm nào đó có thể tự triệu gọi chính mình.. Kiểu hàm như thế được gọi
Trang 1Bài 12 :
ĐỆ QUY
12.1 Mục tiêu
Sau khi hoàn tất bài này học viên sẽ hiểu và vận dụng các kiến thức kĩ năng cơ bản sau:
- Ý nghĩa, phương pháp hoạt động của đệ quy
- Có thể thay vòng lặp bằng đệ quy
12.2 Nội dung
Bất cứ một hàm nào đó có thể triệu gọi hàm khác, nhưng ở đây một hàm nào đó có thể tự
triệu gọi chính mình Kiểu hàm như thế được gọi là hàm đệ quy
Phương pháp đệ quy thường dùng phổ biến trong những ứng dụng mà cách giải quyết có thể được thể hiện bằng việc áp dụng liên tiếp cùng giải pháp cho những tập hợp con của bài toán
Ví dụ 1: tính n!
n! = 1*2*3*…*(n-2)*(n-1)*n với n >= 1 và 0! = 1
Dòng File Edit Search Run Compile Debug Project Option Window Help
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* Ham tinh giai thua */
#include <stdio.h>
#include <conio.h>
void main(void)
{
int in;
long giaithua(int);
printf("Nhap vao so n: ");
scanf("%d", &in);
printf("%d! = %ld.\n", in, giaithua(in));
getch();
}
long giaithua(int in)
{
int i;
long ltich = 1;
if (in == 0)
return (1L);
else
{
for (i = 1; i <= in; i++)
ltich *= i;
return (ltich);
}
}
F1 Help Alt-F8 Next Msg Alt-F7 Prev Msg Alt - F9 Compile F9 Make F10 Menu
Trang 2) Kết quả in ra màn hình
Nhap vao so n: 5
5! = 120
_
Thử lại chương trình với số liệu khác
Với n! = 1*2*3*…*(n-2)*(n-1)*n,
ta viết lại như sau: (1*2*3*…*(n-2)*(n-1))*n = n*(n-1)! … = n*(n-1)*(n-2)!…
) Ta viết lại hàm giaithua bằng đệ quy như sau:
Dòng File Edit Search Run Compile Debug Project Option Window Help
1
2
3
4
5
6
7
8
9
10
/* Ham tinh giai thua */
long giaithua(int in)
{
int i;
if (in == 0)
return (1L);
else
return (in * giaithua(in – 1));
}
F1 Help Alt-F8 Next Msg Alt-F7 Prev Msg Alt - F9 Compile F9 Make F10 Menu
) Chạy lại chương trình, quan sát, nhận xét và đánh giá kết quả
Ví dụ giá trị truyền vào hàm giaithua qua biến in = 5
• Thứ tự gọi thực hiện hàm giaithua
giaithua(in) return(in * giaithua(in – 1))
5
4
3
2
1
5 * giaithua(4) = 5 * ?
4 * giaithua(3) = 4 * ?
3 * giaithua(2) = 3 * ?
2 * giaithua(1) = 2 * ?
1 * giaithua(0) = 1 * ? Khi tham số in = 0 thì return về giá trị 1L (giá trị 1 kiểu long) Lúc này các giá trị ? bắt đầu định trị theo thứ tự ngược lại
• Định trị theo thứ tự ngược lại
giaithua(in) return(in * giaithua(in – 1))
1
2
3
4
5
1 * giaithua(0) = 1 * 1 = 1
2 * giaithua(1) = 2 * 1 = 2
3 * giaithua(2) = 3 * 2 = 6
4 * giaithua(3) = 4 * 6 = 24
5 * giaithua(4) = 5 * 24 = 120 Kết quả sau cùng ta có 5! = 120
Trang 3Thứ tự gọi đệ quy Định trị theo thứ tự ngược lại
Ví dụ 2: Dãy số Fibonacci
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, … Bắt đầu bằng 0 và 1, các số tiếp theo bằng tổng hai số đi trước Dãy Fibonacci được khai báo đệ quy như sau:
Fibonacci(0) = 0
Fibonacci(1) = 1
Fibonacci(n) = Fibonacci(n – 1) + Fibonacci(n – 2)
Dòng File Edit Search Run Compile Debug Project Option Window Help
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* Tinh so fibonacci thu n */
#include <stdio.h>
#include <conio.h>
void main(void)
{
long in;
long fibonacci(long);
printf("Nhap vao so n: ");
scanf("%ld", &in);
printf("Fibonacci(%ld) = %ld.\n", in, fibonacci(in));
getch();
}
long fibonacci(long in)
{
if (in == 0 || in == 1)
return in;
else
return fibonacci(in – 1) + fibonacci(in – 2);
}
F1 Help Alt-F8 Next Msg Alt-F7 Prev Msg Alt - F9 Compile F9 Make F10 Menu
) Kết quả in ra màn hình
Nhap vao so n: 10
Fibonacci(10) = 55
Thử lại chương trình với số liệu khác
5!
5 * 4!
4 * 3!
3 * 2!
2 * 1!
1 * 0!
5! =120
1 * 0! = 1
5 * 4! = 120
4 * 3! = 24
3 * 2! = 6
2 * 1! = 2
Trang 4_
? Sử dụng đệ quy hay vòng lặp
Phương pháp đệ quy không phải bao giờ cũng là giải pháp hữu hiệu nhất.Giải pháp vòng lặp có hiệu quả về mặt thời gian và vùng nhớ Còn với đệ quy mỗi lần gọi đệ quy máy phải dành một số vùng nhớ để trữ các trị, thông số và biến cục bộ Do đó, đệ quy tốn nhiều vùng nhớ, thời gian truyền đối mục, thiết lập vùng nhớ trung gian và trả về kết quả… Nhưng sử dụng phương pháp đệ quy trông chương trình đẹp mắt hơn vòng lặp và tính thuyết phục của nó Điều cốt lõi khi thiết đặt chương trình phải làm thế nào hàm đệ quy có thể chấm dứt thông qua điều kiện cơ bản
12.3 Bài tập
1 Viết hàm đệ quy tính tổng n số nguyên dương đầu tiên:
tong (n) = n + tong (n – 1)