Đệ quy và quay lui

19,017 views

Published on

Published in: Sports, Automotive
8 Comments
3 Likes
Statistics
Notes
No Downloads
Views
Total views
19,017
On SlideShare
0
From Embeds
0
Number of Embeds
268
Actions
Shares
0
Downloads
631
Comments
8
Likes
3
Embeds 0
No embeds

No notes for slide

Đệ quy và quay lui

  1. 1. Chương II: Các thuật toán đệ quy và thuật toán quay lui <ul><li>Thuật toán đệ quy </li></ul><ul><li>Một số bài toán sử dụng thuật toán quay lui </li></ul><ul><li>* Làm bài tập theo nhóm </li></ul>
  2. 2. 1. Thuật toán đệ quy (Recursion) <ul><li>Đại cương </li></ul><ul><li>Phương pháp thiết kế một thuật toán đệ quy </li></ul><ul><li>Xây dựng một thuật toán đệ quy trên một danh sách liên kết đơn </li></ul><ul><li>Xây dựng một thuật toán đệ quy trên một cây nhị phân (lưu trữ móc nối) </li></ul>
  3. 3. Đại cương <ul><li>Chương trình đệ quy là chương trình gọi đến chính nó. </li></ul><ul><li>Một chương trình đệ quy thì không thể gọi đến chính nó mãi mãi mà phải có điểm dừng (trường hợp suy biến). </li></ul>
  4. 4. Phương pháp để thiết kế một thuật toán đệ quy <ul><li>Tham số hoá bài toán </li></ul><ul><li>Phân tích trường hợp chung (biểu diễn bài toán dưới dạng bài toán cùng loại nhưng khác phạm vi giải quyết) </li></ul><ul><li>Xác định trường hợp suy biến </li></ul>
  5. 5. Ví dụ: Sắp xếp mảng a gồm n phần tử <ul><li>Tham số hoá bài toán: </li></ul><ul><li>procedure Sort(dau, cuoi: word); </li></ul><ul><li>Phân tích trường hợp chung: </li></ul><ul><li>Thủ tục Sort(dau, cuoi) có biểu diễn bởi các lệnh: </li></ul><ul><ul><li>Sort(dau+1, cuoi); </li></ul></ul><ul><ul><li>if a[dau]>a[dau+1] then </li></ul></ul><ul><ul><li>begin swap(a[dau],a[dau+1]); </li></ul></ul><ul><ul><li>Sort(dau+1, cuoi); </li></ul></ul><ul><ul><li>end; </li></ul></ul><ul><li>Xác định trường hợp suy biến: dau = cuoi (không làm gì) </li></ul>
  6. 6. procedure Sort(dau, cuoi: word); <ul><li>Begin </li></ul><ul><li>If dau<>cuoi then </li></ul><ul><ul><li>begin Sort(dau+1, cuoi); </li></ul></ul><ul><ul><ul><li>if a[dau]>a[dau+1] then </li></ul></ul></ul><ul><ul><ul><li>begin swap(a[dau],a[dau+1]); </li></ul></ul></ul><ul><ul><ul><li>Sort(dau+1, cuoi); </li></ul></ul></ul><ul><ul><ul><li>end; </li></ul></ul></ul><ul><ul><li>end; </li></ul></ul><ul><li>End; </li></ul><ul><li>Lời gọi từ chương trình chính: Sort(1,n); </li></ul><ul><li>Độ phức tạp tính toán: O(n 2 ) </li></ul>
  7. 7. Ví dụ: Tính a n <ul><li>Tham số hoá bài toán: </li></ul><ul><li>Function Power(a: real; n: byte):real; </li></ul><ul><li>Phân tích trường hợp chung: </li></ul><ul><li>a n = a.a n-1 hay Power(a,n) = a* Power(a,n-1) </li></ul><ul><li>Tr.hợp suy biến: n = 1 ( Power(a,1) = a ) </li></ul><ul><li>Độ phức tạp tính toán: O(n) </li></ul>
  8. 8. Ví dụ: Tính a n (một cách tính khác) <ul><li>Phân tích trường hợp chung: </li></ul><ul><li>Nếu n chẵn: Power(a,n) = sqr(Power(a,n div 2)) </li></ul><ul><li>Nếu n lẻ: Power(a,n) = a*sqr(Power(a,n-1 div 2)) </li></ul><ul><li>Trường hợp suy biến: n = 1 ( Power(a,1) = a ) </li></ul><ul><li>Độ phức tạp tính toán: O(log 2 n) </li></ul>
  9. 9. Xây dựng một thuật toán đệ quy trên một danh sách liên kết đơn <ul><li>Xét khai báo cho trước như sau: </li></ul><ul><li>Type TroNut = ^Nut; </li></ul><ul><li>Nut = Record </li></ul><ul><li>Info: Integer; </li></ul><ul><li>Next: TroNut; </li></ul><ul><li> End; </li></ul><ul><li>Var F: TroNut; {danh sách F} </li></ul>
  10. 10. Viết chương trình con (hàm/thủ tục): CTC([var] F: TroNut; ...) <ul><li>Xem thử có thể biểu diễn: CTC(F, ...) bởi CTC(F^.next, ...) </li></ul><ul><li>Ví dụ: Liệt kê giá trị trường Info của mọi nút thuộc danh sách F </li></ul><ul><li>Procedure List(F: TroNut); </li></ul><ul><li>Begin If F<>nil then </li></ul><ul><li>begin writeln(F^.Info); </li></ul><ul><li>List(F^.Next); </li></ul><ul><li>end; </li></ul><ul><li>End; </li></ul>
  11. 11. Sắp xếp một danh sách F <ul><li>Procedure Sort(F: TroNut); </li></ul><ul><li>Begin </li></ul><ul><li>If (F<>nil) and (F^.Next<>nil) then </li></ul><ul><li>begin Sort(F^.Next); </li></ul><ul><li>If F^.Info>F^.Next^.Info then </li></ul><ul><li>begin swap(F^.Info, F^.Next^.Info); </li></ul><ul><li>Sort(F^.Next); </li></ul><ul><li>end; </li></ul><ul><li>end; </li></ul><ul><li>End; </li></ul>
  12. 12. Hàm Function LaTangDan(F: TroNut): Boolean kiểm tra tính tăng dần của danh sách F <ul><li>Function LaTangDan(F: TroNut) : Boolean; </li></ul><ul><li>Begin </li></ul><ul><li>If (F = nil) or (F^.Next = nil) then LaTangDan := True </li></ul><ul><li>else LaTangDan := (F^.Info< F^.Next^.Info) </li></ul><ul><li>and LaTangDan(F^.Next); </li></ul><ul><li>End; </li></ul>
  13. 13. Thủ tục bổ sung một nút có giá trị trường Info bằng X vào danh sách tăng dần F <ul><li>Procedure BS (var F: TroNut; X:Integer); </li></ul><ul><li>var q: TroNut; </li></ul><ul><li>Begin If (F=nil) or (F^.Info > X) then </li></ul><ul><li> begin new(q); q^.info:=X; q^.next:= F; </li></ul><ul><li> F:=q; </li></ul><ul><li> end </li></ul><ul><li> Else BS(F^.Next, X); </li></ul><ul><li>End; </li></ul>
  14. 14. Thủ tục xoá một nút có giá trị trường Info bằng X của danh sách tăng dần F <ul><li>Procedure Xoa (var F: TroNut; X:Integer); </li></ul><ul><li>var q: TroNut; </li></ul><ul><li>Begin If F<>nil then </li></ul><ul><li> If F^.Info=X then </li></ul><ul><li>begin q:=F; </li></ul><ul><li>F:= F^.Next; </li></ul><ul><li>Dispose(q); </li></ul><ul><li>end </li></ul><ul><li> Else </li></ul><ul><li> If F^.Info < X then Xoa(F^.Next, X); </li></ul><ul><li>End; </li></ul>
  15. 15. Xây dựng một thuật toán đệ quy trên một cây nhị phân lưu trữ móc nối <ul><li>Xét khai báo cho trước như sau: </li></ul><ul><li>Type TroNut = ^Nut; </li></ul><ul><li>Nut = Record </li></ul><ul><li>Info: Integer; </li></ul><ul><li>Left, Right: TroNut; </li></ul><ul><li> End; </li></ul><ul><li>Var T: TroNut; {cây T} </li></ul>
  16. 16. Viết chương trình con (hàm/thủ tục): CTC([var] T: TroNut; ...) <ul><li>Xem thử có thể biểu diễn: CTC(T, ...) bởi CTC(T^.left, ...) và CTC(T^.right, ...) </li></ul><ul><li>Ví dụ: Thủ tục xoá cây T </li></ul><ul><li>Procedure Xoa(T: TroNut); </li></ul><ul><li>Begin If T<> nil then </li></ul><ul><li>begin Xoa(T^.Left); </li></ul><ul><li>Xoa(T^.Right); </li></ul><ul><li>Dispose(T); </li></ul><ul><li>end; </li></ul><ul><li>End; </li></ul>
  17. 17. Ví dụ: Tìm chiều cao của cây T <ul><li>Function ChieuCao(T: Tronut) : Word; </li></ul><ul><li>Begin </li></ul><ul><li>If T = nil </li></ul><ul><li>then ChieuCao := 0 </li></ul><ul><li>else ChieuCao :=max( ChieuCao(T^.left) , ChieuCao(T^.left) )+1; </li></ul><ul><li>End; </li></ul>
  18. 18. Ví dụ: Tìm địa chỉ nút cha của nút trỏ bởi p (thuộc cây T) <ul><li>Function Cha(T, p: TroNut) :TroNut; </li></ul><ul><li>Begin </li></ul><ul><li>If (T=nil) or (T=p) </li></ul><ul><li>then Cha :=nil </li></ul><ul><li>else </li></ul><ul><li>If (T^.Left=p) or (T^.Right=p) </li></ul><ul><li>then Cha :=T </li></ul><ul><li>else </li></ul><ul><li>if Cha(T^.Left, p) <>nil </li></ul><ul><li>then Cha := Cha(T^.Left, p) </li></ul><ul><li>else Cha := Cha(T^.Right, p) ; </li></ul><ul><li>End; </li></ul>
  19. 19. Ví dụ: Kiểm tra cây T là một đống <ul><li>Function LaDong(T: TroNut) : Boolean; </li></ul><ul><li>{ cho kết quả là True nếu cây T là một đống} </li></ul><ul><li>Begin </li></ul><ul><li>If (T = nil) or (T^.Left=nil and T^.Right=nil) </li></ul><ul><li>then LaDong := True </li></ul><ul><li>else If T^.Left=nil and T^.Right<>nil </li></ul><ul><li>then LaDong :=(T^.Info> T^.Right^.Info) and LaDong(T^.Right) </li></ul><ul><li>else If T^.Left<>nil and T^.Right=nil </li></ul><ul><li>then LaDong := (T^.Info> T^.Left^.Info) </li></ul><ul><li>and LaDong(T^.Left) </li></ul><ul><li>else LaDong := (T^.Info> T^.Left^.Info) </li></ul><ul><li>and (T^.Info> T^.Right^.Info) </li></ul><ul><li>and LaDong(T^.Left) </li></ul><ul><li>and LaDong(T^.Right) ; </li></ul><ul><li>End; </li></ul>

×