Giáo trình Lập trình C căn bản Trang 114 Hanoi Aptech Computer Education Center Bà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 Giáo trình Lập trình C căn bản Trang 115 ) 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ả ) Giải thích hoạt động của hàm đệquy giaithua 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. Hanoi Aptech Computer Education Center Giáo trình Lập trình C căn bản Trang 116 Hanoi Aptech Computer Education Center Thứ 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 Giáo trình Lập trình C căn bản Trang 117 _ ? 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) Hanoi Aptech Computer Education Center . 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ớ,. 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