Lập trình phát triển chương trình
0KKỸỸTHUTHUẬẬT LT LẬẬP TRÌNHP TRÌNHKỸ THUẬT PHÁT TRIỂN CHƯƠNG TRÌNHNỘI DUNGHàm và Thủ tụcPhát triển chương trình bằng phương pháp tinh chỉnh dần từng bước.Định nghĩa và sử dụng hàm trong ngôn ngữ CHàm đệ quy1KHKHÁÁI NII NIỆỆM ĐM ĐỆỆQUYQUY?Sức mạnh của đệ quy là gì?Lời giải của bài toán T gọi là đệ quy nếu nó được thực hiện bằng lời giải của bài toán T’ có dạng giống TGiải thuật tương ứng với lời giải đệ quy gọi là giải thuật đệ quy.Biểu diễn giải thuật đệ quy: trong chương trình cần cóthủ tục hay chương trình con.• Đệ quy trực tiếp: trong thủ tục P có chứa lời gọi đến chính nó• Đệ quy gián tiếp: trong thủ tục P có lời gọi thủ tục Q và trong Q có lời gọi đến P.• Cần xác định tình huống, điều kiện để kết thúc đệ quy.2Ví dụ 1. Hàm tính giai thừa• 5! = 5 * 4 * 3 * 2 * 1• Chú ý rằng:– 5! = 5 * 4!– 4! = 4 * 3! .• Có thể thực hiện gọi đệ qui • Điều kiện kết thúc gọi đệ qui: 1! = 0! = 1 – 2! = 2 * 1! = 2 * 1 = 2;– 3! = 3 * 2! = 3 * 2 = 6;3? Bài toán nào có thể dùng đệ quy?Hàm đệ quy thường được viết theo thuật toán sau:if (trường hợp suy biến) {Lời giải bài toán trong trường hợp suy biến;} else {Gọi đệ quy tới hàm với giá trị khác của tham số;} 4Ví dụ 1. Hàm giai thừaVVÍÍDDỤỤVVỀỀ CHƯƠNG TRÌNH Đ CHƯƠNG TRÌNH ĐỆỆQUYQUY⎩⎨⎧>−==0),1(*0,1)(nifnFacnnifnFacfunction Fac(i: integer): integer; beginif i <=1 then Fac := 1else Fac:= i * Fac(i −1);end;55!(a) Sequence of recursive calls. (b) Values returned from each recursive call.Final va lue = 1205! = 5 * 24 = 120 is re turned4! = 4 * 6 = 24 is re turne d2! = 2 * 1 = 2 is returne d3! = 3 * 2 = 6 is re tu rn ed1 returne d5 * 4!14 * 3!3 * 2!2 * 1!5!5 * 4!14 * 3!3 * 2!2 * 1!fig05_14.c (Part 1 of 2)fig05_14.c (Part 1 of 2)1 /* Fig. 5.14: fig05_14.c 2 Recursive factorial function */ 3 #include <stdio.h> 4 5 long factorial( long number ); /* function prototype */ 6 7 /* function main begins program execution */ 8 int main() 9 { 10 int i; /* counter */ 11 12 /* loop 10 times. During each iteration, calculate 13 factorial( i ) and display result */ 14 for ( i = 1; i <= 10; i++ ) { 15 printf( "%2d! = %ld\n", i, factorial( i ) ); 16 } /* end for */ 17 18 return 0; /* indicates successful termination */ 19 20 } /* end main */ 21 1! = 12! = 23! = 64! = 245! = 1206! = 7207! = 50408! = 403209! = 36288010! = 3628800 22 /* recursive definition of function factorial */ 23 long factorial( long number ) 24 { 25 /* base case */ 26 if ( number <= 1 ) { 27 return 1; 28 } /* end if */ 29 else { /* recursive step */ 30 return ( number * factorial( number - 1 ) ); 31 } /* end else */ 32 33 } /* end function factorial */ 8VVÍÍDDỤỤVVỀỀ CHƯƠNG TRÌNH Đ CHƯƠNG TRÌNH ĐỆỆQUYQUYVí dụ 2. Dãy số FibonacciBài toán:• Các con thỏ không bao giờ chết.• Hai tháng sau khi ra đời một cặp thỏ mới sẽ sinh ra một cặp thỏ con (1 đực, 1 cái).• Khi đã sinh con rồi thì cứ mỗi tháng tiếp theo chúng lại sinh được một cặp mới.• Giả sử bắt đầu từ một cặp mới ra đời thì đến tháng thứ n sẽ cóbao nhiêu cặp?9VVÍÍDDỤỤVVỀỀ CHƯƠNG TRÌNH Đ CHƯƠNG TRÌNH ĐỆỆQUYQUYfunction Fib(n: integer):integer;beginif n = 0 then Fib := 0 elseif n = 1 then Fib := 1 elseFib := Fib(n−1) + Fib(n−2);end;⎩⎨⎧>−+−≤=2),2()1(2,1)(nifnFibnFibnifnFib10Gọi functionfibonaccif( 3 )f( 1 )f( 2 )f( 1 ) f( 0 ) return 1return 1 return 0return++return1 /* Fig. 5.15: fig05_15.c 2 Recursive fibonacci function */ 3 #include <stdio.h> 4 5 long fibonacci( long n ); /* function prototype */ 6 7 /* function main begins program execution */ 8 int main() 9 { 10 long result; /* fibonacci value */ 11 long number; /* number input by user */ 12 13 /* obtain integer from user */ 14 printf( "Enter an integer: " ); 15 scanf( "%ld", &number ); 16 17 /* calculate fibonacci value for number input by user */ 18 result = fibonacci( number ); 19 20 /* display result */ 21 printf( "Fibonacci( %ld ) = %ld\n", number, result ); 22 23 return 0; /* indicates successful termination */ 24 25 } /* end main */ 26 Program OutputProgram OutputEnter an integer: 0Fibonacci( 0 ) = 0Enter an integer: 1Fibonacci( 1 ) = 1Enter an integer: 2Fibonacci( 2 ) = 1Enter an integer: 3Fibonacci( 3 ) = 2Enter an integer: 4Fibonacci( 4 ) = 327 /* Recursive definition of function fibonacci */ 28 long fibonacci( long n ) 29 { 30 /* base case */ 31 if ( n == 0 || n == 1 ) { 32 return n; 33 } /* end if */ 34 else { /* recursive step */ 35 return fibonacci( n - 1 ) + fibonacci( n - 2 ); 36 } /* end else */ 37 38 } /* end function fibonacci */ 13VVÍÍDDỤỤVVỀỀ CHƯƠNG TRÌNH Đ CHƯƠNG TRÌNH ĐỆỆQUYQUYVí dụ 3. Đường Hilbert• Đường Hilbert cấp 0 là hình rỗng.• Đường Hilbert cấp i + 1 được thành lập từ 4 đường cấp i được quay theo 1 góc thích hợp và nối với nhau bởi 3 đoạn thẳng.14VVÍÍDDỤỤVVỀỀ CHƯƠNG TRÌNH Đ CHƯƠNG TRÌNH ĐỆỆQUYQUY15VVÍÍDDỤỤVVỀỀ CHƯƠNG TRÌNH Đ CHƯƠNG TRÌNH ĐỆỆQUYQUYx, y - biến toạ độ; h - độ dài của đoạn nối; plot - vẽ từ vị trí hiện tại xác định bởi x, yprocedure A(i:integer);beginif i > 0 thenbeginB(i−1); x := x − h; plot;A(i−1); y := y − h; plot;A(i−1); x := x + h; plot;D(i−1); end; 16VVÍÍDDỤỤVVỀỀ CHƯƠNG TRÌNH Đ CHƯƠNG TRÌNH ĐỆỆQUYQUYprocedure B(i:integer);procedure C(i:integer);procedure D(i:integer);Chương trình chínhBeginread(n, x, y, h);D(n);end.17VVÍÍDDỤỤVVỀỀ CHƯƠNG TRÌNH Đ CHƯƠNG TRÌNH ĐỆỆQUYQUY18BBÀÀI TOI TOÁÁN THN THÁÁP HP HÀÀNNỘỘIIVí dụ 4. Có n đĩa, kích thước khác nhau, có lỗởgiữa và ba cột kí hiệu là A, B, C. Đĩa có thể xếp chồng lên nhau, xuyên qua một cột để tạo thành hình tháp. Giảsử ban đầu n đĩa được đặt ở cột A theo thứ tự lớn dưới nhỏ trên. Cần dời các đĩa đến cột C nhưng vẫn phải giữ thứ tự cũ, với các ràng buộc sau: − Mỗi lần chỉ chuyển một đĩa từ cột này sang cột khác− Đĩa lớn không được chồng lên đĩa nhỏ− Được phép dùng cột B để làm trung gian19BBÀÀI TOI TOÁÁN THN THÁÁP HP HÀÀNNỘỘIITrường hợp 1 đĩa: Chuyển đĩa từ cột A sang cột CTrường hợp 2 đĩa: • Chuyển đĩa thứ nhất (tính từ đĩa trên cùng, hay đĩa nhỏ nhất) từ cột A sang cột B• Chuyển đĩa thứ 2 từ cột A sang cột C• Chuyển đĩa thứ nhất từ cột B sang cột C.Trường hợp n đĩa (n >2)• Chuyển (n−1) đĩa từ cột A sang cột B• Chuyển đĩa thứ n từ cột A sang cột C• Chuyển (n − 1) đĩa từ cột B sang cột C 20BBÀÀI TOI TOÁÁN THN THÁÁP HP HÀÀNNỘỘIIProcedure HanoiTower(n, A, B, C: byte)Begin1. if n = 1 then Chuyển đĩa từ A sang C2. else beginCall HanoiTower(n−1, A, C, B);Call HanoiTower(1, A, B, C);Call HanoiTower(n − 1, B, A, C);end;21BBÀÀI TOI TOÁÁN THN THÁÁP HP HÀÀNNỘỘIICác thuật toán “ Chia để trị” (Divide−and−Conquer)• Để giải bài toán B với bộ dữ liệu S, ta chia s thành các bộ dữliệu con S1, S2, …, Skmà với bộ dữ liệu này, bài toán B giải được bằng một thuật toán đơn giản. Sau đótổ hợp lời giải của các bài toán trên bộ dữ liệu Sisẽ cho lời giải của bài toán B với bộ dữ liệu S. • Thường sử dụng lời gọi đệ quy22THUTHUẬẬT TOT TOÁÁN QUAY LUIN QUAY LUIThuật ngữ: Backtracking [D.H. Lehmer, 1950]Cải tiến từ thuật toán tìm kiếm thôTìm kiếm có hệ thống, theo chiều sâu, trên tập các phương án có thể.“Thử và sai” (“Trial-and-Error”)Thường sử dụng đệ quyCác ví dụ:• Bài toán Quân Hậu• Bài toán Mã đi tuần• Bài toán Hôn nhân bền vững23KHI NKHI NÀÀO KHÔNG SO KHÔNG SỬỬDDỤỤNG ĐNG ĐỆỆQUY?QUY?Thuật toán đệ quyfunction Fac(i: integer): integer; {lưu ý nên dùng số nguyên lớn}beginif i <=1 then Fac := 1else Fac:= i * Fac(i − 1);end; 24KHI NKHI NÀÀO KHÔNG SO KHÔNG SỬỬDDỤỤNG ĐNG ĐỆỆQUY?QUY?Thuật toán không đệ quy (Sử dụng vòng lặp)function Fac2(i: integer):integer;begini := 0; F := 1;while i < n dobegini := i +1; F := F * i;end;end;25Đệ qui và lặp:Lặp• Lặp: rõ ràng, kiểm soát trong quá trình chạy chương trình• Đệ qui: lặp lại lời gọi hàmKết thúc• Lặp: điều kiện lặp sai (false)• Đệ qui: nhận ra tình huống, điều kiện để kết thúc đệ quiCả hai đều có thể lặp vô hạnCân nhắc• Chọn giữa lặp và gọi đệ qui?26KHI NKHI NÀÀO KHÔNG SO KHÔNG SỬỬDDỤỤNG ĐNG ĐỆỆQUY?QUY?Đệ quy là tốt nhất?Khi nào nên dùng đệ quyNhững mô hình bài toán nên tránh dùng đệ quy:P ≡ if B then S; P end;hay P ≡ S; if B then P end; 27BBÀÀI TI TẬẬPP1. Xây dựng các hàm số sau bằng phương pháp đệ quy:f(x,n) = xn , (n >=0)s(n) = (2n)!2. Viết chương trình sử dụng hàm đệ quy để tính UCLN của hai số nguyên dương theo quy tắc sau:• Nếu x= y thì UCLN(x, y) = x• Nếu x > y thì UCLN(x, y) = UCLN(x − y, y);• Nếu x < y thì UCLN(x, y) = UCLN(x, y −x); 28BBÀÀI TI TẬẬPP3. Viết chương trình sử dụng hàm đệ quy để vẽ đường Hilber cấp k (k nhập vào từ bàn phím)4. Viết chương trình sử dụng đệ quy để giải bài toán Tháp Hà Nội . 0KKỸỸTHUTHUẬẬT LT LẬẬP TRÌNHP TRÌNHKỸ THUẬT PHÁT TRIỂN CHƯƠNG TRÌNHNỘI DUNGHàm và Thủ tục Phát triển chương trình bằng phương pháp tinh chỉnh. với nhau bởi 3 đoạn thẳng.14VVÍÍDDỤỤVVỀỀ CHƯƠNG TRÌNH Đ CHƯƠNG TRÌNH ĐỆỆQUYQUY15VVÍÍDDỤỤVVỀỀ CHƯƠNG TRÌNH Đ CHƯƠNG TRÌNH ĐỆỆQUYQUYx, y - biến toạ độ; h -