Academia.eduAcademia.edu
NHẬP MÔN LẬP TRÌNH KỸ THUẬT LẬP TRÌNH ĐỆ QUY 1 & VC BB Nội dung 1 Tổng quan về đệ quy 2 Các vấn đề đệ quy thông dụng 3 Phân tích giải thuật & khử đệ quy 4 Các bài toán kinh điển NMLT - Kỹ thuật lập trình đệ quy 2 & VC BB Bài toán Cho S(n) = 1 + 2 + 3 + ầ + n =>S(10)? S(11)? S(10) = 1 + 2 + … + 10 = 55 S(11) = 1 + 2 + … + 10 + 11 = 66 = S(10) = 55 + 11 + 11 = 66 NMLT - Kỹ thuật lập trình đệ quy 3 & VC BB 2 bước giải bài toán Bước 2. Thế ngược S(n)  Xác định kết quả bài toán đồng dạng từ đơn giản đến phức tạp  Kết quả cuối cùng. = S(n-1) + n S(n-1) = S(n-2) + n-1 … Bước 1. Phân tích  Phân tích thành bài toán đồng dạng nhưng đơn giản hơn.  Dừng lại ở bài toán đồng dạng đơn giản nhất có thể xác định ngay kết quả. = … S(1) + … = S(0) + 1 S(0) = 0 NMLT - Kỹ thuật lập trình đệ quy 4 & VC BB Khái niệm đệ quy Khái niệm Vấn đề đệ quy là vấn đề được định nghĩa bằng chính nó. Ví dụ Tổng S(n) được tính thông qua tổng S(n-1). 2 điều kiện quan trọng  Tồn tại bước đệ quy.  Điều kiện dừng. NMLT - Kỹ thuật lập trình đệ quy 5 & VC BB Hàm đệ quy trong NNLT C Khái niệm  M t hƠm đ ợc gọi lƠ đệ quy n u bên trong thơn của hƠm đó có lời gọi hƠm lại chính nó m t cách trực ti p hay gián ti p. ầ Hàm(ầ) { ầ ầ Lời gọi Hàm ầ ầ ầ } ĐQ trực tiếp ầ Hàm1(ầ) { ầ ầ Lời gọi Hàm2 ầ ầ ầ } ầ Hàm2(ầ) { ầ ầ Lời gọi Hàmx ầ ầ ầ } ĐQ gián tiếp NMLT - Kỹ thuật lập trình đệ quy 6 & VC BB Cấu trúc hàm đệ quy <Kiểu> <TênHƠm>(TS) { Phần dừng (Base step) if (<ĐK dừng>) • Phần khởi tính toán hoặc { điểm kết thúc của thuật toán … • Không chứa phần đang được return <Giá trị>; định nghĩa } Phần đệ quy } (Recursion step) … … Lời gọi Hàm• Có sử dụng thuật toán đang được định nghĩa. … NMLT - Kỹ thuật lập trình đệ quy 7 & VC BB Phân loại TUY N TÍNH NH PHÂN H PHI TUY N T 1 2 Trong thân hàm có duy nhất một lời gọi hàm gọi lại chính nó một cách tường minh. Trong thân hàm có hai lời gọi hàm gọi lại chính nó một cách tường minh. NG 3 Trong thân hàm này có lời gọi hàm tới hàm kia và bên trong thân hàm kia có lời gọi hàm tới hàm này. 4 Trong thân hàm có lời gọi hàm lại chính nó được đặt bên trong thân vòng lặp. NMLT - Kỹ thuật lập trình đệ quy 8 & VC BB Đệ quy tuyến tính Ví dụ Tính S(n) = 1 + 2 + … + n  S(n) = S(n – 1) + n ĐK dừng: S(0) = 0 C u trúc ch ng trình <Kiểu> TênHàm(<TS>) { if (<ĐK đừng>) { … return <Giá Trị>; } … TênHàm(<TS>); … } .: Chương trình :. long Tong(int n) { if (n == 0) return 0; return Tong(n–1) + n; } NMLT - Kỹ thuật lập trình đệ quy 9 & VC BB Đệ quy nhị phân Ví dụ C u trúc ch ng trình <Kiểu> TênHàm(<TS>) { if (<ĐK dừng>) { … return <Giá Trị>; } … TênHàm(<TS>); … … TênHàm(<TS>); … } Tính số hạng thứ n của dãy Fibonacy: f(0) = f(1) = 1 f(n) = f(n – 1) + f(n – 2) n > 1 ĐK dừng: f(0) = 1 và f(1) = 1 .: Chương trình :. long Fibo(int n) { if (n == 0 || n == 1) return 1; return Fibo(n–1)+Fibo(n–2); } NMLT - Kỹ thuật lập trình đệ quy 10 & VC BB Đệ quy hỗ tương Ví dụ C u trúc ch ng trình <Kiểu> TênHàm1(<TS>) { if (<ĐK dừng>) return <Giá trị>; … TênHàm2(<TS>); … } <Kiểu> TênHàm2(<TS>) { if (<ĐK dừng>) return <Giá trị>; … TênHàm1(<TS>); … } Tính số hạng thứ n của dãy: x(0) = 1, y(0) = 0 x(n) = x(n – 1) + y(n – 1) y(n) = 3*x(n – 1) + 2*y(n – 1) ĐK dừng: x(0) = 1, y(0) = 0 .: Chương trình :. long yn(int n); long xn(int n) { if (n == 0) return 1; return xn(n-1)+yn(n-1); } long yn(int n) { if (n == 0) return 0; return 3*xn(n-1)+2*yn(n-1); } NMLT - Kỹ thuật lập trình đệ quy 11 & VC BB Đệ quy phi tuyến Ví dụ C u trúc ch ng trình <Kiểu> TênHàm(<TS>) { if (<ĐK dừng>) { … return <Giá Trị>; } … Vòng lặp { … TênHàm(<TS>); … } … } Tính số hạng thứ n của dãy: x(0) = 1 x(n) = n2x(0) + (n-1)2x(1) + … + 22x(n – 2) + 12x(n – 1) ĐK dừng: x(0) = 1 .: Chương trình :. long xn(int n) { if (n == 0) return 1; long s = 0; for (int i=1; i<=n; i++) s = s + i*i*xn(n–i); return s; } NMLT - Kỹ thuật lập trình đệ quy 12 & VC BB Các bước xây dựng hàm đệ quy Thông số hóa bài toán Tìm thu t giải t ng quát Tìm các tr ờng hợp suy bi n (neo)  T ng quát hóa bƠi toán cụ thể thƠnh bƠi toán t ng quát.  Thông số hóa cho bƠi toán t ng quát  VD: n trong hƠm tính t ng S(n), ầ  Chia bƠi toán t ng quát ra thƠnh:  Ph n không đệ quy.  Ph n nh bài toán trên nh ng kích th ớc nhỏ h n.  VD: S(n) = S(n ậ 1) + n, ầ  Các tr ờng hợp suy bi n của bƠi toán.  Kích th ớc bài toán trong tr ờng hợp nƠy lƠ nhỏ nh t.  VD: S(0) = 0 NMLT - Kỹ thuật lập trình đệ quy 13 & Cơ chế gọi hàm và STACK BB main() { } …; A(); …; D(); …; } { } main …; D(); …; D A C() A() { B() { } …; B(); …; C(); …; …; D() { } …; C B STACK VC D D B B B C A A A A A A A D M M M M M M M M M M M Thời gian NMLT - Kỹ thuật lập trình đệ quy 14 & VC BB Nhận xét C ch gọi hƠm dùng STACK trong C phù hợp cho giải thu t đệ quy vì:  L u thông tin trạng thái còn dở dang m i khi gọi đệ quy.  Thực hiện xong m t l n gọi c n khôi phục thông tin trạng thái tr ớc khi gọi.  Lệnh gọi cuối cùng s hoƠn t t đ u tiên. NMLT - Kỹ thuật lập trình đệ quy 15 & VC BB Ví dụ gọi hàm đệ quy Tính số hạng thứ 4 của dưy Fibonacy F(4) 5 3 F(3) 1 F(1) 2 F(2) 3 + 2 + 1 F(0) 5 + 1 F(1) 2 F(2) 1 F(1) 2 + 1 F(0) NMLT - Kỹ thuật lập trình đệ quy 16 & VC BB Một số lỗi thường gặp Công thức đệ quy ch a đúng, không tìm đ ợc bài toán đồng dạng đ n giản h n (không h i tụ) nên không giải quy t đ ợc v n đề. Không xác đ nh các tr ờng hợp suy bi n ậ neo (điều kiện dừng). Thông điệp th ờng gặp là StackOverflow do:  Thu t giải đệ quy đúng nh ng số l n gọi đệ quy quá lớn làm tràn STACK.  Thu t giải đệ quy sai do không h i tụ hoặc không có điều kiện dừng. NMLT - Kỹ thuật lập trình đệ quy 17 & VC BB Các vấn đề đệ quy thông dụng Đệ quy?? NMLT - Kỹ thuật lập trình đệ quy 18 & VC BB 1.Hệ thức truy hồi Khái niệm  Hệ thức truy hồi của 1 dưy An lƠ công thức biểu diễn ph n tử An thông qua 1 hoặc nhiều số hạng tr ớc của dưy. A0 A1 … An-2 An-1 An hồi Hàm truy A0 A1 … An-2 An-1 An hồi Hàm truy NMLT - Kỹ thuật lập trình đệ quy 19 & VC BB 1.Hệ thức truy hồi Ví dụ 1  Vi trùng cứ 1 giờ lại nhơn đôi. V y sau 5 giờ s có m y con vi trùng n u ban đ u có 2 con? Giải pháp  Gọi Vh lƠ số vi trùng tại thời điểm h.  Ta có: • Vh = 2Vh-1 • V0 = 2  Đệ quy tuy n tính với V(h)=2*V(h-1) và điều kiện dừng V(0) = 2 NMLT - Kỹ thuật lập trình đệ quy 20 & VC BB 1.Hệ thức truy hồi Ví dụ 2  Gửi ngơn hƠng 1000 USD, lưi su t 12%/năm. Số tiền có đ ợc sau 30 năm là bao nhiêu? Giải pháp  Gọi Tn lƠ số tiền có đ ợc sau n năm.  Ta có: • Tn = Tn-1 + 0.12Tn-1 = 1.12Tn-1 • V(0) = 1000  Đệ quy tuy n tính với T(n)=1.12*T(n-1) và điều kiện dừng V(0) = 1000 NMLT - Kỹ thuật lập trình đệ quy 21 & VC BB 2.Chia để trị (divide & conquer) Khái niệm  Chia bài toán thành nhiều bƠi toán con.  Giải quy t từng bƠi toán con.  T ng hợp k t quả từng bƠi toán con để ra lời giải. NMLT - Kỹ thuật lập trình đệ quy 22 & VC BB 2.Chia để trị (divide & conquer) Ví dụ 1  Cho dãy A đư sắp x p thứ tự tăng. Tìm v trí ph n tử x trong dưy (n u có) Giải pháp  mid = (l + r) / 2;  N u A[mid] = x  trả về mid.  Ng ợc lại • N u x < A[mid]  tìm trong đoạn [l, mid ậ 1] • Ng ợc lại  tìm trong đoạn [mid + 1, r]  Sử dụng đệ quy nh phơn. NMLT - Kỹ thuật lập trình đệ quy 23 & VC BB 2.Chia để trị (divide & conquer) Ví dụ 2  Tính tích 2 chu i số cực lớn X vƠ Y Giải pháp  X = X2n-1ầXnXn-1ầX0, Y = Y2n-1ầYnYn-1ầY0  Đặt XL=X2n-1ầXn, XN=Xn-1ầX0  X=10nXL+XN  Đặt YL=Y2n-1ầYn, YN=Yn-1ầY0  Y=10nYL+YN   X*Y = 102nXLYL + 10n(XLYL+XNYN)+XNYN  và XLYL+XNYN = (XL-XN)(YN-YL)+XLYL+XNYN NMLT - Kỹ thuật lập trình đệ quy 24 & VC BB 2.Chia để trị (divide & conquer) M t số bƠi toán khác  BƠi toán tháp HƠ N i  Các giải thu t sắp x p: QuickSort, MergeSort  Các giải thu t tìm ki m trên cơy nh phơn tìm ki m, cơy nh phơn nhiều nhánh tìm ki m. L u ý  Khi bƠi toán lớn đ ợc chia thƠnh các bƠi toán nhỏ h n mƠ những bƠi toán nhỏ h n này không đ n giản nhiều so với bƠi toán gốc thì không nên dùng kỹ thu t chia để tr . NMLT - Kỹ thuật lập trình đệ quy 25 & VC BB 3.Lần ngược (Backtracking) Khái niệm  Tại b ớc có nhiều lựa chọn, ta chọn thử 1 b ớc để đi ti p.  N u không thƠnh công thì “l n ng ợc” chọn b ớc khác.  N u đư thƠnh công thì ghi nh n lời giải nƠy đồng thời “l n ng ợc” để truy tìm lời giải mới.  Thích hợp giải các bƠi toán kinh điển nh bài toán 8 h u vƠ bƠi toán mư đi tu n. NMLT - Kỹ thuật lập trình đệ quy 26 & 3.Lần ngược (Backtracking) VC BB Ví dụ  Tìm đ ờng đi từ X đ n Y. D A B Y X C NMLT - Kỹ thuật lập trình đệ quy 27 & VC BB Một số bài toán kinh điển THÁP HÀ N I TÁM H U ầ # $ @ 1 2 3 1 3 2 MÃ ĐI TU N PHÁT SINH HOÁN V NMLT - Kỹ thuật lập trình đệ quy 28 & VC BB Tháp Hà Nội Mô tả bƠi toán  Có 3 c t A, B vƠ C vƠ c t A hiện có N đĩa.  Tìm cách chuyển N đĩa từ c t A sang c t C sao cho: • M t l n chuyển 1 đĩa • Đĩa lớn h n phải nằm d ới. • Có thể sử dụng các c t A, B, C lƠm c t trung gian. NMLT - Kỹ thuật lập trình đệ quy 29 & VC BB Tháp Hà Nội N đĩa A  C = N-1 ? đĩa A  B + Đĩa N A  C + N-1 đĩa B  C 1 … N-1 N Cột nguồn A Cột trung gian B Cột đích C NMLT - Kỹ thuật lập trình đệ quy 30 & VC BB Tám hậu Mô tả bƠi toán  Cho bƠn cờ vua kích th ớc 8x8  Hãy đặt 8 hoƠng h u lên bƠn cờ nƠy sao cho không có hoƠng h u nƠo “ăn” nhau: • Không nằm trên cùng dòng, cùng c t • Không nằm trên cùng đ ờng chéo xuôi, ng ợc. NMLT - Kỹ thuật lập trình đệ quy 31 & VC BB Tám hậu – Các dòng 0 1 n đường 2 3 4 5 6 7 NMLT - Kỹ thuật lập trình đệ quy 32 & VC BB Tám hậu – Các cột 0 1 2 3 4 5 6 7 n đường NMLT - Kỹ thuật lập trình đệ quy 33 & VC BB Tám hậu – Các đường chéo xuôi 0 2n-1 đường 1 2 3 4 5 6 14 13 12 11 10 9 8 7 NMLT - Kỹ thuật lập trình đệ quy 34 & VC BB Tám hậu – Các đường chéo ngược 2n-1 đường 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 NMLT - Kỹ thuật lập trình đệ quy 35 & VC BB Tám hậu – Các dòng i=2 j=3 j+i=5 j-i+n-1=8 NMLT - Kỹ thuật lập trình đệ quy 36 & VC BB Mã đi tuần Mô tả bƠi toán  Cho bƠn cờ vua kích th ớc 8x8 (64 ô)  Hãy đi con mã 64 n ớc sao cho m i ô ch đi qua 1 l n (xu t phát từ ô b t kỳ) theo lu t: 5 6 4 7 3 8 2 1 NMLT - Kỹ thuật lập trình đệ quy 37 & VC BB Phân tích giải thuật đệ quy Sử dụng cơy đệ quy (recursive tree)  Giúp hình dung b ớc phơn tích vƠ th ng ợc.  B ớc phân tích: đi từ trên xuống d ới.  B ớc th ng ợc đi từ trái sang phải, từ d ới lên trên.  Ý nghĩa • Chiều cao của cơy  Đ lớn trong STACK. • Số nút  Số lời gọi hƠm. NMLT - Kỹ thuật lập trình đệ quy 38 & VC BB Nhận xét  u điểm  Sáng sủa, dễ hiểu, nêu rõ bản ch t v n đề.  Ti t kiệm thời gian thực hiện mư nguồn.  M t số bƠi toán r t khó giải n u không dùng đệ qui. Khuy t điểm  Tốn nhiều b nhớ, thời gian thực thi lơu.  M t số tính toán có thể b lặp lại nhiều l n.  M t số bƠi toán không có lời giải đệ quy. NMLT - Kỹ thuật lập trình đệ quy 39 & VC BB Ví dụ cây đệ quy Fibonacy F(4) F(3) F(2) F(1) F(2) F(1) F(0) F(1) F(0) Lặp lại NMLT - Kỹ thuật lập trình đệ quy 40 & VC BB Khử đệ quy (Tham khảo) Khái niệm  Đ a các bài toán đệ quy về các bƠi toán không sử dụng đệ quy.  Th ờng sử dụng vòng lặp hoặc STACK tự tạo. ầ NMLT - Kỹ thuật lập trình đệ quy 41 & VC BB Tổng kết Nh n xét  Ch nên dùng ph ng pháp đệ quy để giải các bài toán kinh điển nh giải các v n đề “chia để tr ”, “l n ng ợc”.  V n đề đệ quy không nh t thi t phải giải bằng ph ng pháp đệ quy, có thể sử dụng ph ng pháp khác thay th (khử đệ quy)  Tiện cho ng ời l p trình nh ng không tối u khi chạy trên máy.  B ớc đ u nên giải bằng đệ quy nh ng từng b ớc khử đệ quy để nơng cao hiệu quả. 42 NMLT - Kỹ thuật lập trình đệ quy & VC BB Bài tập thực hành Bài 1: Các bƠi t p trên mảng sử dụng đệ quy. Bài 2: Vi t hƠm xác đ nh chiều dƠi chu i. Bài 3: Hiển th n dòng của tam giác Pascal.  a[i][0] = a[i][i] = 1  a[i][k] = a[i-1][k-1] + a[i-1][k] Bài 4: Vi t hƠm đệ quy tính C(n, k) bi t  C(n, k) = 1 n u k = 0 hoặc k = n  C(n, k) = 0 n u k > n  C(n ,k) = C(n-1, k) + C(n-1, k-1) n u 0<k<n NMLT - Kỹ thuật lập trình đệ quy 43 & VC BB Bài tập thực hành Bài 5: Đ i 1 số th p phơn sang c số khác. Bài 6: BƠi toán 8 h u Bài 7: Bài toán mã đi tu n Bài 8: Tính các t ng truy hồi. NMLT - Kỹ thuật lập trình đệ quy 44