1. Trang chủ
  2. » Công Nghệ Thông Tin

Kỹ thuật khử đệ quy

5 15 0

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 5
Dung lượng 46,5 KB

Nội dung

Đệ quy là quả tim trong các nghiên cứu lý thuyết cũng như thực hành tính toán, đã thể hiện rất nhiều sức mạnh và có ưu điểm trong nhiều bài toán. Tuy nhiên bài này tôi lại đi ngược với công việc chúng ta thường làm: khử đệ quy, đó là vấn đề cũng có nhiều thú vị và đáng để chúng ta xem xét.

Kỹ thuật khử đệ quy Trần Đức Thiện Đệ quy tim nghiên cứu lý thuyết thực hành tính tốn, thể nhiều sức mạnh có ưu điểm nhiều tốn Tuy nhiên lại ngược với công việc thường làm: khử đệ quy, vấn đề có nhiều thú vị đáng để xem xét Khử đệ quy biến thủ tục đệ quy thành thủ tục chứa vịng lặp mà khơng ảnh hưởng đến yếu tố khác, thay đổi thuật tốn Ví dụ hàm đệ quy tính n! số Fibonaci F(n) ta thay vịng lặp để tính; Đó khơng phải phương pháp khử đệ quy mà tơi muốn nói Trong trường hợp tổng quát, khử đệ quy việc làm phức tạp khó khăn hàm n! hay F(n) ta dùng thuật tốn khơng đệ quy, số toán, đệ quy bắt buộc Bạn nói rằng, sử dụng đệ quy, vừa ngắn gọn dễ hiểu, vừa dễ cài đặt Nhưng có đơi khi, hạn hẹp nhớ dành cho chương trình khơng cho phép làm điều đó; biết rằng, ngơn ngữ máy khơng có đệ quy, trình biên dịch phải có nhiệm vụ khử đệ quy Và bạn thực gặp rắc rối với thủ tục đệ quy mơi trường lập trình mà khơng cung cấp khả gọi đệ quy Khử đệ quy giúp bạn giữ nguyên thuật toán đệ quy mà khơng có lời gọi đệ quy, chương trình chạy mơi trường lập trình Khử đệ quy thực chất phải làm công việc trình biên dịch thủ tục, là: Đặt tất giá trị biến cục địa thị vào ngăn xếp (Stack), quy định giá trị tham số cho thủ tục chuyển tới vị trí bắt đầu thủ tục, thực câu lệnh Sau thủ tục hồn tất phải lấy khỏi ngăn xếp địa trả giá trị biến cục bộ, khôi phục biến chuyển tới địa trả Để dễ theo dõi lấy ví dụ với tốn cụ thể tốn duyệt Giả sử có nhị phân lưu trữ biến động t định nghĩa: type pnode = ^node; node = record inf : variable; { truong luu tru thong tin } l,r : pnode; end; var t : pnode; Xuất phát từ nút gốc t, cần duyệt qua hết theo thứ tự từ trái qua phải Chương trình đệ quy sau: procedure Try(t : pnode); begin if t nil then begin visit(t); Try(t^.l); Try(t^.r); end; end; Trước hết thấy lệnh gọi đệ quy thứ hai khử dễ dàng khơng có mã lệnh theo sau Khi lệnh thực thủ tục Try( ) gọi với tham số t^.r lệnh gọi kết thúc thủ tục Try hành kết thúc Chương trình viết lại sau dùng goto: procedure try(t : pnode); label 0; begin : if t = nil then exit; visit(t); try(t^.l); t := t^.r; goto 0; end; Đó kỹ thuật tiếng gọi khử đệ quy phần cuối Việc khử lần gọi đệ quy lại đòi hỏi phải làm nhiều việc Giống trình biên dịch phải tổ chức ngăn xếp (Stack) để lưu trữ biến cục bộ, tham số, sử dụng thủ tục: Push(t): Đặt biến t vào đỉnh Stack; Hàm pop: lấy giá trị đỉnh stack Hàm stackempty: Báo hiệu Stack rỗng khơng có giá trị trả có biến cục t nên nạp vào stack chưa xử lý bước lấy biến đỉnh stack để xử lý nút Chương trình khử lời gọi đệ quy thứ hai sau: procedure try(t : pnode); label 0,1,2; begin 0: if t = nil then goto 1; visit(t); push(t); t := t^.l; goto 0; : t := t^.r; goto 0; : if stackempty then exit; t := pop; goto 2; end; Thủ tục diễn giải thô ý tưởng để bạn dễ hiểu, thị goto rườm ra, viết lại cách có cấu trúc sau: procedure try(t : pnode); label 0; begin 0: while t nil begin visit(t); push(t^.r); t := t^.l end; if stackempty then exit; t := pop; goto 0; end; Bây giờ, loại bỏ hoàn toàn thị goto tránh trường hợp nạp nút rỗng vào stack ta có thủ tục duyệt khơng đệ quy chuẩn sau, bạn thấy chất không khác thủ tục đệ quy mấy: procedure try(t : pnode); begin push(t); repeat t := pop; visit(t); if t^.l nil then push(t^.l); if t^.r nil then push(t^.r); until stackempty; end; Để minh hoạ cụ thể cho kỹ thuật này, tơi xin trình bày với bạn chương trình xếp nhanh(QuickSort) khử đệ quy: Program Quick_sort_Khu_de_quy_Th; const inp = 'FileName.inp'; out = 'FileName.out'; maxstack = 1000; maxn = 1000; type it = longint; var a : array[1 maxn] of it; sl,sr : array[1 maxstack] of word; n,top : it; f : text; procedure push(l,r : word); begin inc(top); sl[top] := l; sr[top] := r; end; procedure pop(var l,r : word); begin l := sl[top]; r := sr[top]; dec(top); end; function stackEmpty : boolean; begin stackempty := top = 0; end; procedure init; begin top := 0; end; procedure nhap; var i : it; begin assign(f,inp); reset(f); readln(f,n); for i := to n read(f,a[i]); close(f); end; procedure sort(l1,r1 : word); var l,r,i,j : word; t,tg : it; begin push(l1,r1); repeat pop(l,r); i := l; j := r; t := a[(l+r) div 2]; repeat while a[i] < t inc(i); while t < a[j] dec(j); if i j; if i < r then push(i,r); if l < j then push(l,j); until stackEmpty; end; procedure xuat; var i : it; begin assign(f,out); rewrite(f); for i := to n write(f,a[i],' '); close(f); end; BEGIN nhap; init; sort(1,n); xuat; END Trong lúc khảo sát tính hiệu việc khử đệ quy Cịn bạn trung thành với thủ tục Try đệ quy mình, thực ngắn gọn, dễ hiểu dễ cài đặt Dù khơng dùng đến nghiên cứu thêm việc không thừa Biết đâu sau bạn trở thành người viết chương trình dịch sao, − viết bổ ích cho bạn Chào thân hẹn gặp lại ... = nil then exit; visit(t); try(t^.l); t := t^.r; goto 0; end; Đó kỹ thuật tiếng gọi khử đệ quy phần cuối Việc khử lần gọi đệ quy lại đòi hỏi phải làm nhiều việc Giống trình biên dịch phải tổ... stackempty; end; Để minh hoạ cụ thể cho kỹ thuật này, tơi xin trình bày với bạn chương trình xếp nhanh(QuickSort) khử đệ quy: Program Quick_sort_Khu_de _quy_ Th; const inp = 'FileName.inp'; out... BEGIN nhap; init; sort(1,n); xuat; END Trong lúc khảo sát tính hiệu việc khử đệ quy Còn bạn trung thành với thủ tục Try đệ quy mình, thực ngắn gọn, dễ hiểu dễ cài đặt Dù khơng dùng đến nghiên cứu

Ngày đăng: 21/05/2021, 12:41

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w