Bài giảng Cấu trúc dữ liệu và giải thuật – Bài 3: Đệ quy (Recursion)

39 78 0
Bài giảng Cấu trúc dữ liệu và giải thuật – Bài 3: Đệ quy (Recursion)

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Bài giảng Cấu trúc dữ liệu và giải thuật – Bài 3: Đệ quy (Recursion) cung cấp những kiến thức về khái niệm về đệ quỵ; ví dụ về đệ quỵ; đệ quy đuôi; bài toán tháp Hanoi. Mời các bạn cùng tham khảo bài giảng để phục vụ cho học tập và nghiên cứu.

Cấu trúc liệu giải thuật Bài Đệ quy (Recursion) Lecturer: PhD Ngo Huu Phuc Tel: 0438 326 077 Mob: 098 5696 580 Email: ngohuuphuc76@gmail.com @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University Bài Đệ quy Nội dung:     Khái niệm đệ quy Ví dụ đệ quy Đệ quy (Tail Recursion) Bài tốn tháp Hanoi Tham khảo: Kyle Loudon – Mastering Algorithms with C Chapter – Recursion Hanoi Tower (Web page) @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.1 Khái niệm đệ quy (1/6)  Với phần lập trình viên, để giải tốn lớn, sử dụng trình dạng đệ quy  Ta nói m ột đối tượng đệ qui đối tượng bao gồm phận đối tượng định nghĩa dạng @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.1 Khái niệm đệ quy (2/6)  Nguyên lý đệ quy cho phép hình thành tốn từ  Trong tính tốn, để giải vấn đề sử dụng hàm đệ quy (hàm gọi với tham số thay đổi)  Như vậy, hàm đệ quy hàm gọi lại  Với bước, hàm thay đổi thông tin đầu vào cho kết ngày gần với mục tiêu toán @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.1 Khái niệm đệ quy (3/6) • Giả sử cần tính giai thừa số nguyên dương n • Giai thừa n viết: n!, tích phần tử từ n đến • Ví dụ, 5! = (5)(4)(3)(2)(1) • Có thể thực tính giai thừa vịng lặp thơng thường để tính tích • Một cách tiếp cận khác, sử dụng đệ quy, cơng thức tính giai thừa viết dạng: n! = (n)(n - 1)(n - 2) (1) @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.1 Khái niệm đệ quy (4/6) • Có thể định nghĩa n! theo cách khác, tích n giai thừa nhỏ • Như vậy, ta có n! = n * (n – 1)! • Ta x lý (n - 1)! giống n!, với tham số nhỏ • Ta có, (n - 1)! = (n – 1) * (n - 2)!, • Tương tự, (n - 2)! = (n – 2) * (n - 3)!, trình kết thúc n=1 • Với cách tiếp cận dạng đệ quy, định nghĩa lại cách tính giai thừa dạng: n! = iif(n=0, 1, n * (n-1)!) @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.1 Khái niệm đệ quy (5/6) Có thể hình dung đệ quy qua bước chính: quay xuôi (winding) quay ngược (unwinding) Tại bước winding, lời giải tốn gọi lại      Với bước winding, lời gọi dừng thỏa mãn điều kiện dừng Điều kiện dừng thơng thường định nghĩa bước đến tốn sở, giải trực tiếp Với hàm đệ quy cần có điều kiện dừng, không lặp vô hạn @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.1 Khái niệm đệ quy (6/6)  Khi bước winding kết thúc, bước unwinding thực hiện, toán nhỏ xem xét theo thứ tự ngược lại  Bước dừng lại trình đến tốn gốc Q trình đệ quy kết thúc @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.2 Ví dụ đệ quy (1/6) Ví dụ 1: Tính n! F(n) = n* F(n-1) n > F(n) = n = n = Tính F(4) = ? Bước Winding Bước UnWinding F(4) = * F(3) F(4) = * = 24 F(3) = * F(2) F(3) = * = F(2) = * F(1) F(2) = * = F(1) = F(1) = @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University Ví dụ 1: Tính n! Ví dụ 1: Tính n! đệ quy long factorial(int n) #include { #include if((n==0)||(n==1)) return 1; long factorial(int); else return n*factorial(n-1); void main() } { int n; printf("Nhap vao mot so: "); scanf("%d",&n); printf("Gia tri cua giai thua: %ld",factorial(n)); getch(); } 10 @Copyright Dr Ngo Huu Phuc, Le Quy Don Technical University 3.3 Đệ quy (4/6) Ví dụ 3: Tính tổng chuỗi số F(a,1,b) = b F(a,n,b) = F(a,n-1,b+a[n-1]) n > Cho a[4] = [1,7,3,5] Tính F(a,4,a[4]) = ? Bước Winding F(a,4,5) = F(a,3,8) Bước UnWinding Khơng thực F(a,3,8) = F(a,2,15) F(a,2,15) = F(a,1,16) F(a,1,16) = 16 25 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University Ví dụ 3: Tính tổng đệ quy Ví dụ 3: Tính tổng đệ quy đuôi long sum_tail(int * a, int n, long b) #include { #include if(n==0)return b; long sum_tail(int*, int, long); void main() else return sum_tail(a,n-1,b+a[n-1]); } { int n; int a[100]; printf("Nhap vao so pt: "); scanf("%d",&n); for(int i=0;i Tính F(4,0,1) = ? Bước Winding F(4,0,1) = F(3,1,1) Bước UnWinding Khơng thực F(3,1,1) = F(2,1,2) F(2,1,2) = F(1,2,3) F(1,2,3) = 27 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University Ví dụ 4: Tính Fibonacci đệ quy Ví dụ 4: Tính Fibonacci đệ quy long fibonacci(int n, int a, int b) #include { #include if (n==1) return b; long fibonacci(int, int, int); void main() else return fibonacci(n-1,b,a+b); } { int n; printf("Nhap vao n: "); scanf("%d",&n); printf("Fibonacci cua %d: %ld",n,fibonacci(n,0,1)); getch(); } 28 @Copyright Dr Ngo Huu Phuc, Le Quy Don Technical University 3.3 Đệ quy (6/6) Ví dụ 5: Euler GCD (greatest common divisor) Algorithm (n > m) F(n,m) = m n div m = F(n, m) = F(m, n mod m) n mod m Tính F(54,21) = ? Bước Winding F(54,21) = F(21,12) Bước UnWinding Không thực F(21,12) = F(12,9) F(12,9) = F(9,3) F(9,3) = 29 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University Ví dụ 5: Tính ước số chung lớn Ví dụ 5: Hàm Euler GCD int Ackermann(int m, int n) #include { #include if((m>=0) && (n==0)) return m+1; int Ackermann(int, int); if((n>0) && (m==0)) return Ackermann(1,n-1); if((m>=1) && (n>0)) return Ackermann(Ackermann(m-1,n), n-1); void main() { } int m, n; printf("Nhap vao m= "); scanf("%d",&m); printf("Nhap vao n= "); scanf("%d",&n); printf("Ackermann cua %d va %d: %d",m,n,Ackermann(m,n)); getch(); } 30 @Copyright Dr Ngo Huu Phuc, Le Quy Don Technical University 3.4 Tháp Hà nội (1/8)  Bài toán nhà toán học người Pháp Edouard Lucas đưa vào năm 1883  Bài toán Tháp Hà nội giới thiệu nhiều tài liệu thuật toán Bên cạnh đó, nhiều web sites đề cập tới toán 31 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.4 Tháp Hà nội (2/8) Bài tốn  Có n đĩa có kích thước khác có stacks có tên A, B, C  Ban đầu, n đĩa đặt stack A, cho khơng có đĩa lớn nằm đĩa nhỏ  Nhiệm vụ đặt chuyển tất đĩa stack A sang stack C Sử dụng stack B làm trung gian trình chuyển  Mỗi lần chuyển đĩa khơng có đĩa lớn nằm đĩa nhỏ 32 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.4 Tháp Hà nội (3/8) 33 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.4 Tháp Hà nội (4/8)  Để giải tốn trên, số bước chuyển đĩa bao nhiêu?  Để trả lời câu hỏi trên, cần đưa cách đệ quy tối ưu phân tích chúng  Có thể phân tích khơng trường hợp tổng qt hóa, khơng xét đĩa? 34 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.4 Tháp Hà nội (5/8) Giải pháp đệ quy:  Ban đầu, đĩa lớn đặt đáy stack A  Giả sử chuyển sang stack C (cách tốt để tiếp cận toán), n-1 đĩa nhỏ phải chuyển sang stack B  Như vậy, cần chuyển n-1 đĩa nhỏ từ A sang B, sử dụng C làm stack trung gian  Sau thực việc trên, cần chuyển n-1 đĩa lại từ B sang C, sử dụng stack A làm stack trung gian 35 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.4 Tháp Hà nội (6/8)  Ký hiệu: "A ==> B" có nghĩa chuyển đĩa đỉnh A sang B  Giải thuật: Function HanoiTower (n, A,B,C) if n < then return HanoiTower (n-1, A,C,B) A ==> B HanoiTower (n-1, C,B,A) End Function 36 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University 3.4 Tháp Hà nội (7/8) Phân tích toán với n = 37 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University Tháp Hà nội #include "stdio.h" void HanoiTower(int m, char a, char b, char c) #include "conio.h" { void HanoiTower(int, char, char, char); if(m>0) { void main() HanoiTower(m-1,a,c,b); { int m; printf("Chuyen dia %d tu %c sang %c\n",m,a,b); printf("Nhap vao so dia m = "); HanoiTower(m-1,c,b,a); scanf("%d",&m); } printf("Ket qua cac buoc \n"); HanoiTower(m,'A','C','B'); } getch(); } 38 @Copyright Dr Ngo Huu Phuc, Le Quy Don Technical University 3.4 Tháp Hà nội (8/8) Thời gian giới hạn:  Gọi T(n) số phép chuyển đĩa giải thuật để chuyển n đĩa  Từ giải thuật, thấy: T(n) = n < T(n) = 2T(n-1) + n >  Giải tốn trên, ta có: T(n) = 2n - với n >  Như vậy, T(n) hữu hạn, giải thuật dừng 39/39 @Copyright by PhD Ngo Huu Phuc, Le Quy Don Technical University ... Phuc, Le Quy Don Technical University 3.3 Đệ quy đuôi - Tail Recursion (1/6)  Hàm đệ quy gọi đệ quy đuôi - tail recursive – lời gọi đệ quy hàm công việc cuối trình đệ quy  Trong trình đệ quy, trạng.. .Bài Đệ quy Nội dung:     Khái niệm đệ quy Ví dụ đệ quy Đệ quy (Tail Recursion) Bài tốn tháp Hanoi Tham khảo: Kyle Loudon – Mastering Algorithms with C Chapter – Recursion Hanoi... PhD Ngo Huu Phuc, Le Quy Don Technical University 3.1 Khái niệm đệ quy (2/6)  Nguyên lý đệ quy cho phép hình thành tốn từ  Trong tính tốn, để giải vấn đề sử dụng hàm đệ quy (hàm gọi với tham

Ngày đăng: 24/09/2020, 04:26

Tài liệu cùng người dùng

Tài liệu liên quan