Chúng ta sẽ thấy rõ vai tròcủa công cụ này trong định nghĩa văn phạm, định nghĩa cú pháp ngôn ngữ, địnhnghĩa một số cấu trúc dữ liệu…Nội dung của bài đề tài được trình bày sau đây sẽphần
Trang 1
Báo cáo đề tài toán
rời rạc
Trang 2Mục luc
LỜI MỞ ĐẦU 12
Phần I: GIỚI THIỆU 13
Phần II: ĐỆ QUY VÀ CÁCH KHỬ ĐỆ QUY 14
Chương I: NHỮNG HIỂU BIẾT VỀ ĐỆ QUY 14
1.1 -Khái niệm đệ quy 14
1.1.1 Khái niệm: 14
1.2 -Thuật toán đệ quy: 16
1.2.1 Khái niệm : 16
1.3 Ưu nhược điểm của đệ quy: 18
1.3.1 Ưu điểm: 18
1.3.2 Nhược điểm: 19
Chương II : CHƯƠNG TRÌNH CON ĐỆ QUY 19
2.1 Các phương pháp xây dựng chương trình con đệ quy: 19
2.1.1 Định nghĩa chương trình con đệ quy: 19
2.1.2 Cấu trúc của một chương trình con đệ quy: 19
2.2 Phương pháp xây dựng chương trình con đệ quy: 21
2.3 Cách thực hiện của đệ quy: 24
2.3.1 Hiện thực đa xử lý:xử lý đồng thời 24
2.3.2 Hiện thực đơn xử lý: vấn đề vùng nhớ 25
Thuật giải đệ quy 26
3.1-Vấn đề khử đệ quy: 27
3.2 Một số phương pháp khử đệ quy: 28
3.2.1 Khử đệ quy bằng vòng lặp: 28
3.2.1.1 Hàm tính giá trị của dãy dữ liệu mô tả bằng hồi quy: 28
3.2.1.2 Các thủ tục khử đệ quy dạng đệ quy đuôi: 30
3.2.1.3 Các hàm khử đệ quy dạng đệ quy đuôi ( tail-recusive ) 32
Trang 3YÊU CẦU CỦA ĐỀ TÀI:
Thuật toán đệ quy và cách khử đệ quy:
1 Trình bày hiểu biết về thuật toán đệ quy, ưu nhược điểm của đệquy
2 Các phương pháp xây dựng chương trình con đệ quy, cách thựchiện chương trình đệ quy, cơ chế cấp phát và quản lý bộ nhớ chochương trình đệ quy
3 Vấn đề khử đệ quy và một số phương pháp khử đệ quy, có ví dụminh họa
4 Cài đặt thuật toán Selectionsort thực hiện việc sắp xếp một dãy n
số nguyên theo chiều tăng dần bằng phương pháp đệ quy sau đókhử đệ quy
Trang 4
LỜI MỞ ĐẦU
Toán rời rạc là một lĩnh vực của toán học nghiên cứu các đối tượng rờirạc.Chúng ta sẽ sử dụng công cụ rời rạc khi phải đếm các đối tượng, khi nghiêncứu quan hệ giữa các tập rời rạc, khi phân tích các quá trình hữu hạn.Đồng thờitầm quan trọng của toán rời rạc được nâng cao là nhờ việc cất giữ và xử lý thôngtin trên máy tính có bản chất là các quá trình rời rạc.Các quá trình rời rạc ấy được
xử lý và biểu diễn thông qua các chương trình, các thuật toán cụ thể.Khi nói đếncác thuật toán trong toán rời rạc ta không thể không nói đến đệ quy và giải thuậtcủa đệ quy Đệ quy không những giúp người lập trình giải quyết tốt các bài toán
mà còn giúp nâng cao tư duy toán, rèn luyện kỹ thuật lập trình.Tuy rằng bên cạnhgiải thuật đệ quy vẫn có những giải thuật lặp khá đơn giản và hữu hiệu,chẳng hạnnhư giải thuật lặp tính n! nhưng đệ quy vẫn có vai trò xứng đáng của nó, cónhững bài toán việc nghĩ ra lời giải đệ quy thuận lợi hơn nhiều so với lời giải lặp
và có những giải thuật đệ quy thật sự cũng có hiệu lực cao nữa Một điều cần nóithêm về đệ quy là: Về mặt định nghĩa công cụ đệ quy đã cho phép xác định mộttập vô hạn các đối tượng bằng một phát biểu hữu hạn Chúng ta sẽ thấy rõ vai tròcủa công cụ này trong định nghĩa văn phạm, định nghĩa cú pháp ngôn ngữ, địnhnghĩa một số cấu trúc dữ liệu…Nội dung của bài đề tài được trình bày sau đây sẽphần nào giúp các bạn hiểu sâu sắc hơn về đệ quy và các giải thuật liên quan tớinó.Trong đề tài này chúng tôi trình bày gồm có 4 chương.Mỗi chương chúng tôi
đã cố gắng trình bày ngắn gọn, trực tiếp vào bản chất của vấn đề, đồng thời sửdụng cài đặt tất cả các chương trình bằng ngôn ngữ lập trình pascal,hy vọng sẽmang lại sự gần gũi, dễ hiểu cho các sinh viên,mong rằng nó sẽ thực sự giúp íchcho các bạn trong quá trình nghiên cứu về đệ quy
Sinh viên nhóm 5 rất cảm ơn các thầy cô giáo trong bộ môn khoa họcmáy tính đã hướng dẫn chúng em trong quá trình thực hiện đề tài này.Mặc dù rất
cố gắng nhưng không tránh khỏi những thiếu sót và hạn chế,rất mong được sựtham gia, đóng góp ý kiến bổ sung của thầy cô và các bạn cho đề tài này
Chúng tôi xin chân thành cảm ơn!
Trang 5Phần I: GIỚI THIỆU
Toán học rời rạc là một trong những môn cơ sở được giảng dạy ở cáckhoa công nghệ thông tin hiện nay.Nhằm đáp ứng thêm nhu cầu đa dạng về kiếnthức cho các bạn sinh viên về toán rời rạc,đề tài này chúng tôi nghiên cứu về đệquy và cách khử đệ quy,đây là bài toán rất nhỏ được sử dụng trong toán rời rạcnhưng khi xét về vai trò thì nó là một phần không thể thiếu của toán rời rạc.Nộidung đề tài chúng tôi trình bày gồm bốn chương, mỗi chương chúng tôi cố gắngtrình bày cô đọng các nội dung,cụ thể như:
Chương 1: Sơ lược về đệ quy,qua chương này các bạn sẽ nắm đượcnhững khái niệm cơ bản về đệ quy, và phần nào hiểu hơn về nó
Chương 2: Chương trình con đệ quy và một số vấn đề liên quan đếnnó,qua chương này các bạn sẽ hiểu thêm về cách xây dựng và sử dụngcác hàm, cũng như các thủ tục của đệ quy
Chương 3: Chương này chúng tôi trình bày cách khử đệ quy, khử đệquy ở đây được hiểu là một phương pháp làm mất đi tính đệ quy củamột chương trình đệ quy.Giải thuật này cũng mang một ý nghĩa hết sứcquan trọng trong quá trình giải các bài toán liên quan
Chương 4: Chương này chúng tôi cài đăt một bài toán ví dụ giúp cácbạn hiểu thêm một cách sâu sắc hơn về những gì chúng tôi đã nêu ởtrên
Nói một cách tổng quát, qua bài đề này chúng tôi mong giúp cho mọingười hiểu một cách sâu sắc hơn về đệ quy, và từ đó áp dụng thành thạo nó trongviệc giải quyết các bài toán có liên quan
**********************************
Trang 6
Phần II: ĐỆ QUY VÀ CÁCH KHỬ ĐỆ QUY
Chương I: NHỮNG HIỂU BIẾT VỀ ĐỆ QUY
1.1 -Khái niệm đệ quy
1.1.1 Khái niệm:
Đệ quy là một khái niệm tồn tại trong cuộc sống, trong toán học cũng nhưtrong lập trình Đệ quy cho một phương pháp ngắn gọn và sáng sủa để mô tả cácđối tựơng cũng như một số quá trình Như vậy đệ quy là một phương pháp xácđịnh tập hợp các đối tượng thỏa mãn một yêu cầu nào đó
Một đối tượng được gọi là đệ quy nếu nó bao gồm chính nó như một bộ phậnhoặc đối tượng được định nghĩa dưới dạng của chính nó
Ví dụ về đệ quy:
-Ví dụ 1:
Đặt 2 chiếc gương cầu đối diện nhau Trong chiếc gương thứ nhất chứahình chiếc gương thứ hai, trong chiếc gương thứ hai chứa hình chiếc gương thứnhất nên tất nhiên nó chứa lại hình ảnh của chính nó trong chiếc gương thứ nhất…
Ở một góc nhìn hợp lý ta có thể thấy một dãy ảnh vô hạn của hai chiếc gương -Ví dụ 2:
Trên vô tuyến truyền hình có lúc ta thấy có những hình ảnh đệ quy như sau:phát thanh viên ngồi bên máy vô tuyến truyền hình, trên màn hình của máy này lại
có chính hình ảnh của phát thanh viên ấy ngồi bên máy vô tuyến và cứ như thế… -Ví dụ 3:
Trang 7Mọi quá trình đệ quy gồm có hai phần:
Một vài trường hợp cơ bản nhỏ nhất có thể được giải quyết mà khôngcần đệ quy
Một phương pháp chung có thể giảm một trường hợp thành một hoặcnhiều trường hợp nhỏ hơn,và nhờ đó việc giảm nhỏ vấn đề có thể tiếntriển cho đến kết quả cuối cùng là các trường hợp cơ bản
1.1.2 Phân loại đệ quy:
Người ta phân đệ quy làm hai loại: + Đệ quy trực tiếp
+ Đệ quy gián tiếp
* Đệ quy trực tiếp: là loại đệ quy mà đối tượng được mô tả trực tiếp qua nó: A
mô tả qua A, B, C… Trong đó B, C không chứa A
Ví dụ:
1 Mô tả đệ quy cây gia phả: gia phả của một người bao gồm người đó vàgia phả của cha và gia phả của mẹ
Trang 82 Mô tả đệ quy thủ tục chọn hoa hậu: + Chọn hoa hậu của từng khu vực + Chọn hoa hậu của các hoa hậu.
* Đệ quy gián tiếp: Là loại đệ quy mà đối tượng được được mô tả gián tiếp qua
nó: A mô tả qua A1, A2,….,An Trong đó có một Ai được mô tả qua A
Ví dụ: Mô tả dạng tổng quát một chương trình viết trên ngôn ngữ lập trìnhpascal:
Một chương trình pascal gồm:
Đầu chương trình ( head ) gồm : program tên;
Thân chương trình ( blok ) gồm:
+ Khai báo unit, định nghĩa hàm,nhãn, kiểu dữ liệu, khai báo biến + Định nghĩa các chương trình con
- Đầu chương trình con: *procedure tên thủ tục ( danh sách thông
đệ quy được gọi là giải thuật đệ quy hay thuật toán đệ quy ( T’<T )
* Định nghĩa một hàm đệ quy hay thủ tục đệ quy gồm hai phần:
Trang 9- Phần neo ( anchor ): phần này được thực hiện khi mà công việc quá đơn giản
có thể giải trực tiếp chứ không cần phải nhờ đến một bài toán con nào cả
- Phần đệ quy: Trong trường hợp bài toán chưa thể giải được bằng phần neo, taxác định những bài toán con và gọi đệ quy giải các bài toán con đó Khi đã có lờigiải( đáp số ) của những bài toán rồi thì phối hợp chúng lại để giải bài toán đangquan tâm
Phần đệ quy thể hiện tính quy nạp của lời giải Phần neo cũng rất quan trọng bởi
nó quy định tới tính hữu hạn dừng của lời giải
* Nói một cách tổng quát một giải thuật đệ quy được biểu diễn như một bộ
P gồm mệnh đề S ( không chứa yếu tố đệ quy ) và P: P P [ S , P ]
Thực thi giải thuật đệ quy có thể dẫn tới một tiến trình gọi đệ quy không kếtthúc khi đó không có khả năng gặp trường hợp neo, vì vậy quan tâm đến điều kiệndừng của một giải thuật đệ quy luôn được đặt ra Để kiểm soát quá trình gọi đệquy của giải thuật đệ quy P người ta thường gắn thao tác gọi P với việc kiểm tramột điều kiện B xác định và biến đổi qua mỗi lần gọi P, quá trình gọi P sẽ dừngkhi P không còn thỏa mãn
Mô hình tổng quát của một giải thuật đệ quy với sự quan tâm đến điều kiệndừng sẽ là:
P if B then P [ S, P ] hoặc P P [ S, if B then P ]
Thông thường với giải thuật đệ quy P để đảm bảo P sẽ dừng sau n lần gọi
ta chọn B là ( n > 0) Mô hình giải thuật đệ quy khi đó có dạng:
P ( n ) if ( n > 0 ) then P [ S , P ( n -1 ) ]; hoặc
P ( n ) P [ S , if ( n > 0) then P ( n – 1 ) ] ;
Trong các ứng dụng thực tế số lần gọi đệ quy ( độ sâu đệ quy ) khôngnhững phải hữu hạn mà còn phải đủ nhỏ, bởi vì mỗi lần gọi đệ quy sẽ cần mộtvùng nhớ mới trong khi vùng nhớ cũ vẫn phải duy trì
1.2.2 Ví dụ:
Xét bài toán tìm một từ trong từ điển :
Trang 10Ta có thuật toán dưới dạng giả mã như sau:
BEGIN
IF ( từ điển chỉ có một trang ) THEN ( tìm từ trong trang này ) ELSE
BEGIN
+ ( chia đôi từ điển );
+ ( xác định xem nửa nào của từ điển chứa từ cần tìm)
IF ( từ đó nằm ở nửa trước của từ điển )
THEN ( tìm từ đó trong nửa trước )
ELSE ( tìm từ đó trong nửa sau );
END;
END
Ta thấy sau mỗi lần từ điển được tách đôi thì một nửa thích hợp sẽ lại đượctìm kiếm bằng một cách như đã dùng trước đó Có một trường hợp đặc biệt, khácvới mọi trường hợp trước, sẽ đạt được sau nhiều lần tách đôi, đó là trường hợp từđiển chỉ còn duy nhất một trang Lúc đó việc tách đôi ngừng lại và bài toán đã đủnhỏ để ta có thể giải quyết trực tiếp bằng cách tìm từ mong muốn trên trang đó,chẳng hạn bằng cách tìm tuần tự Trường hợp đặc biệt này gọi là trường hợp suybiến
1.3 Ưu nhược điểm của đệ quy:
1.3.1 Ưu điểm:
Công cụ mạnh, diễn đạt tư duy rất rõ ràng, chặt chẽ
Ngắn gọn, có khả năng định nghĩa một tập hợp rất lớn các đối tượng bằngmột số các câu lệnh hữu hạn
Làm chương trình trông đẹp mắt, dễ đọc, dễ hiểu và chương trình đượcnêu bật rõ ràng hơn
Trang 111.3.2 Nhược điểm:
Đệ quy tốn bộ nhớ nhiều hơn khi không đệ quy vì cứ mỗi lần gọi đệ quylại cần thêm một vùng nhớ mới trong khi vùng nhớ cũ vẫn được duy trì
Tốc độ thực hiện chương trình chậm hơn khi không đệ quy
Chương II : CHƯƠNG TRÌNH CON ĐỆ QUY
2.1 Các phương pháp xây dựng chương trình con đệ quy:
2.1.1 Định nghĩa chương trình con đệ quy:
Định nghĩa:
Một chương trình con (hàm hoặc thủ tục) được gọi là đệ quy nếu trong quátrình thực hiện nó có phần phải gọi đến chính nó
2.1.2 Cấu trúc của một chương trình con đệ quy:
Cấu trúc chính của một chương trình con đệ quy gồm hai phần: Phần cơ sở
và phần đệ quy
Phần cơ sở: Chứa tác động của hàm hoặc thủ tục với một số giá trị cụthển ban đầu của tham số.Nó bao gồm các trường hợp dừng mà có thểđược giải quyết ngay (trường hợp duy biến)
Phần đệ quy: Định nghĩa giá trị cần tác động cho giá trị hiện thời cáctham số bằng các tác động đã được định nghĩa trước đây với các kíchthước tham số nhỏ hơn (Là phần trong thuật toán có yêu cầu gọi đệquy,tức là yêu yêu cầu thực hiện lại thuật toán ở cấp độ nhỏ hơn (điềukiện kiểm soát đệ quy))
Trang 12- Ví dụ : Hàm tính giai thừa của số tự nhiên n ( tính n! ).
Ta có chương trình con đệ quy sau:
Function gt ( n: byte ) : longint;
Begin
If n= 0 then gt:= 1 ( phần cơ sở )
Else gt:= n* gt ( n - 1); ( phần đệ quy ) End;
Trong ví dụ trên, qui trình thực hiện như sau:
Như vậy kết quả cuối cùng trả về là 6 Ta có: 3! = 6
- Một ví dụ khác như sau: Ta xây dựng chương trình con tính số fibonaci Function Fibo ( n: integer) : integer ;
Trang 132.2 Phương pháp xây dựng chương trình con đệ quy:
Để xây dựng giải thuật một bài toán có tính đệ quy bằng phương pháp đệ quy ta cần thực hiện tuần tự 3 nội dung sau:
- Thông số hóa bài toán
- Tìm các trường hợp neo cùng giải thuật giải tương ứng
- Tìm giải thuật giải trong trường hợp tổng quát bằng phân rã bài toán theo kiểu đệ quy
Thông số hoá bài toán.
Tổng quát hóa bài toán cụ thể cần giải thành bài toán tổng quat (một họ các bàitoán chúa bài toán cần giải), tìm ra các thông số cho bài toán tổng quat đặc biệt là nhóm các thông số biểu thị kích thước của bài toán-các thông số điểu khiển (các thông số mà độ lớn của chúng đặc trưng cho độ phức tạp của bài toán, và giảm đi qua mỗi lần gọi đệ quy)
Ví dụ: n trong hàm FAC(n); a,b trong hàm USCLN(a,b)
Phát hiện các trường hợp suy biến (neo) và tìm giải thuật cho các trường hợp này.
Trang 14Đây là các trường hợp suy biến của bài toán tổng quat, là các trường hợp tươngứng với các giá trị biên cuả các biến điều khiển (trường hợp kích thước bài toán nhỏ nhất), mà giải thuật giải không đệ qui (thường rất đơn giản).
Ví dụ:
FAC(1)=1, USCLN(a,0)=a
Phân rã bài toán tổng quát theo phương thức đệ quy.
Tìm phương án (giải thuật) giải bài toán trong trường hợp tổng quat bằng cách phân chia nó thành các thành phần mà hoặc có giải thuật không đệ quy hoặc là bài toán trên nhưng có kích thước nhỏ hơn
Ví dụ: FAC(n)=n*FAC(n-1)
Đệ quy là một công cụ cho phép người lập trình tập trung vào bước chính yếu của giải thuật mà không phải lo lắng tại thới điểm khởi đầu về cách kết nối bước chính yếu này với các bước khác Khi cần giải quyết một vấn đề, bước tiếp cận đầu tiên nên làm thường là xem xét một vài ví dụ đơn giản, và chỉ sau khi đã hiểu được chúng một cách kỹ lưỡng, chúng ta mới thử cố gắng xây dựng một phương pháp tổng quát hơn Một vài điểm quan trọng trong việc thiết kế một giải thuật đệ quy được liệt kê sau đây:
Tìm bước chính yếu Hãy bắt đầu bằng câu hỏi “Bài toán này có thể được
chia nhỏ như thế nào?” hoặc “Bước chính yếu trong giai đọan giữa sẽ được thực hiện như thế nào?” Nên đảm bảo rằng câu trả lời của bạn đơn giản nhưng có tính tổng quat Không nên đi từ điểm khởi đầu hay điểm kết thúc của bài toán lớn, hoặc sa vào quá nhiểu trường hợp đặc biệt (do chúng chỉ phù hờp vói các bài toán nhỏ) Khi đã có được một bước nhỏ và đơn giản
để hướng tới lời giải, hay tự hỏi rằng những khúc mắc còn lại của bài toán
có thể được giải quyết bằng cách tương tự hay không, để sủa lại phương pháp của bạn cho tổng quát hơn, nếu cần thiết Ngoại trừ những định nghĩa
Trang 15toán học thể hiện sự đệ quy quá rõ ràng, một điều thú vị mà chúng ta sẽ lần lượt gặp trong những chương sau la, khi những bài toán cần được giải quyếttrên những cấy trúc dữ liệu mà định nghĩa mang tính chất đệ quy nhu danh sách, chuỗi ký tự biểu diễn biểu thức số học, cây, hay đồ thi… thì giải pháp hướng tới một giải thuật đệ quy là rất dễ nhình thấy.
Tìm điều kiện dừng Điều kiện dừng chỉ ra rằng bài toán hoặc một phần
nào đó của bài toán đã được giải quyết Điều kiện dừng thường là trường hợp nhỏ, đặc biệt, có thể được giải quyết một cách dễ dàng không cần đệ quy
Phác thảo giải thuật Kết hợp điểu kiện dừng với bước chính yếu của bài
toán, sử dụng lệnh if để chọn lụa giũa chúng Đến đây thì chúng ta có thể viết hàm đệ quy, trong đó mô tá cách mà bước chính yếu được tiến hành cho đến khi gặp được điểu kiện dùng Mỗi lần gọi đệ quy hoặc là phải giải quyết một phần của bài toán khi gặp một trong các điều kiện dừng, hoặc là phải giảm kích thước bài toán hướng dần đến điều kiện dừng
Kiểm tra sự kết thúc Kế tiếp, và cũng là điều tối quan trọng, là phải chắc
chắn việc gọi đệ quy sẽ không bị lặp vô tận Bắt đầu từ một trường hợp chung, qua một số bước hữu hạn, chúng ta cần kiểm tra liệu điều kiện dừng
có khả năng xảy ra để quá trình đệ quy kết thúc hay không Trong bất kỳ một giải thuật nào, khi một lần gọi hàm không phải làm gì, nó thường quay
về một cách êm thấm Đối với giải thuật đệ quy, điều này rất thường xảy ra,
do việc gọi hàm mà không phải làm gì thường là một điều kiện dừng Do
đó, cần lưu ý rằng việc gọi hàm mà không làm gì thường không phải là mộtlỗi trong trường hợp của hàm đệ quy
Kiểm tra lại mọi trường hợp đặc biệt Cuối cùng chúng ta cũng cần bảo
đảm rằng giải thuật của chúng ta luôn đáp ứng mọi trường hợp đặc biệt
Vẽ cây đệ quy Công cụ chính để phân tích các giải thuật đệ quy là cây đệ
quy Như chúng ta đã thấy trong bài toán Tháp Hà Nội, chiểu cao của cây
đệ quy kiên quan mật thiết đến tổng dung lượng bộ nhớ mà chương trình
Trang 16cần đến, và kích thước tổng cộng của cây phản ánh số lần thực hiện bước chính yếu và cũng là tổng thời gian chay chương trình Thông thường chúng ta nên vẽ cây đệ quy cho một hoặc hai trường hợp đơn giản của bài toán của chúng ta vì nó sẽ chỉ dẫn cho chúng ta nhiều điều
2.3 Cách thực hiện của đệ quy:
Khi nghiên cứu về phần này chúng ta phải lưu ý câu hỏi về cách thực hiện một chương trình đệ quy trong máy tính cần được tách rời khỏi câu hỏi về sử dụng
đệ quy để thiết kế giải thuật
Trong giai đoạn thiết kế, chúng ta nên sử dụng mọi phương pháp giải quyết vấn đề mà chúng tỏ ra thích hợp với bài toán, đệ quy là một trong các công cụ hiệuquả và linh hoạt này
Trong giai đoạn thực hiện, chúng ta cần tìm xem phương pháp nào trong số các phương pháp sẽ là tốt nhất so với từng tình huống Có ít nhất hai cách để hiện thực đệ quy trong hệ thống máy tính Quan điểm chính của chúng ta khi xem xét hai cách hiện thực khác nhau dưới đây là, cho dù có sự hạn chế về không gian và thời gian chúng cũng nên được tách riêng ra khỏi quá trình thiết kế giải thuật, các loại thiết bị tính toán khác nhau Chúng ta sẽ tìm hiểu hai cách hiện thực đa xử lý
và đơn xử lý dưới đây
2.3.1 Hiện thực đa xử lý:xử lý đồng thời.
Có lẽ rằng cách suy nghĩ tự nhiên về quá trình hiện thực của đệ quy là các hàmkhông chiếm những phần riêng trong cùng một máy tính, mà chúng sẽ được thực hiện trên những máy khác nhau, Bằng cách này, khi một hàm cần gọi một hàm khác, nó khởi động chiếc tương ứng, và khi máy này kết thúc công việc, nó sẽ trả
về chiếc máy ban đầu kết quả tính được để chiếc máy ban đầu có thể tiếp tục công việc Nếu một hàm gọi đệ quy chính nó hai lần, đơn giản nó chỉ cần khởi động hai chiếc máy khác để thực hiện những dòng lệnh y như những dòng lệnh mà nó đangthực hiện Khi hai máy hoàn tất công việc chúng trả kết quả về cho máy gọi chúng
Trang 17Nếu chúng cần gọi đệ quy, dĩ nhiên chúng cũng khởi động những chiếc máy khác nữa.
Thông thường bộ xử lý trung ương là thành phần đắt nhất trong hệ thống máy tính, nên bất kỳ ý nghĩ nào về một hệ thống có nhiều hơn một bộ xử lý cũng cần phải xem xét đến xự lãng phí song song sẽ trở nên bình thường
Với đa xử lý, nhưng người lập trình sẽ không còn xem xét các giải thuật chỉ như một chuỗi tuyến tính các hành động, thay vào đó, cần phải nhận ra một số phần của giải thuật có thể thực hiện song song Cách xử lý này còn được gọi là xử
lý đồng thời (concurrent) Việc nghiên cứu về xử lý đồng thời và các phương phápkết nối giữa chúng hiện tại là một đề tài nghiên cứu trong khoa học máy tính, một điều ,chắc chắn là nó sẽ cải tiến cách mà giải thuật sẽ được mô ta và hiện thực trong nhiều năm tới
2.3.2 Hiện thực đơn xử lý: vấn đề vùng nhớ.
Để xem xét làm cách nào mà đệ quy có thể được thực hiện trong một
hệ thống chỉ có một bộ xử lý chúng ta nhớ lại cơ cấu ngăn xếp của các lần gọi hàm đã được giới thiệu ơ đầu chương Một hàm khi được gọi phải có một vùng nhớ riêng để chứa các biến cục bộ và các tham trị của nó, kể cả các trị trong các thanh ghi và địa chỉ quay về khi nó chuẩn bị gọi một hàm khác Sau khi hàm kết thúc , nó sẽ không còn cần đến bất kỳ thứ gì trong vùng nhớ dành riêng cho nó nữa Thực sự là không có sự khác nhau giữa việc gọi một hàm đệ quy và việc gọi một hàm không đệ quy Khi một hàm chưa kết thúc , vùng nhớcủa nó sẽ bất khả xâm phạm Một lần gọi hàm đệ quy cũng chưa là một lần gọihàm riêng biệt Chúng ta cần chú ý rằng hai lần gọi đệ quy là hoàn toàn khac nhau , để chung ta không lẫn vùng nhớ của chúng khi chúng chưa kết thúc Đối với hàm đệ quy , những thông tin lưu trữ dành cho lần gọi ngoài cần giữ được cho đến khi nó kết thúc , như vậy một lần gọi bên trong phải sử dụng một vùng nhớ khác làm vùng nhớ riêng của nó
Trang 18Đối với một hàm không đệ quy , vùng nhớ có thể là vùng nhớ cố định vàđược dành cho lâu dài, do chúng không biết rằng một lần gọi hàm sẽ được trả
về trước khi hàm có thể lại được gọi lần nữa,và sau khi gọi trước được trả
về , các thông tin trong vùng nhớ của nó không cần thiết nữa Vùng nhớ lâu dài được dành sẵn cho các hàm không đệ quy có thể gây lẵng phí lớn, do nhưng khi hàm không được yêu cầu thực hiện , vùng nhớ đó không thể được
sử dụng vào mục đích khác Đó cũng là cách quản lý vùng nhớ dành cho các hàm của các phiên bản cũ cuả các ngôn ngữ như FORTRAN và COBOL, và chính điều này cũng là lý do mà các ngôn ngữ này không cho phép đệ quy
Sau đây là một số chương trình con đệ quy được minh họa như sau:
BÀI TOÁN THÁP HÀ NỘI Thuật giải đệ quy
đặt tên các cọc là A, B, C những tên này có thể chuyển ở các bước khác nhau (ở đây: A = Cột Nguồn, B = Cột Đích, C = Cột Trung Gian)
gọi n là tổng số đĩa
đánh số đĩa từ 1 (nhỏ nhất, trên cùng) đến n (lớn nhất, dưới cùng)
Để chuyển n đĩa từ cọc A sang cọc B thì cần:
1 chuyển n-1 đĩa từ A sang C Chỉ còn lại đĩa #n trên cọc A
2 chuyển đĩa #n từ A sang B
3 chuyển n-1 đĩa từ C sang B cho chúng nằm trên đĩa #n
Phương pháp trên được gọi là thuật giải đệ quy: để tiến hành bước 1 và 3, áp dụng lại
thuật giải cho n-1 Toàn bộ quá trình là một số hữu hạn các bước, vì đến một lúc nào đó thuật giải sẽ áp dụng cho n = 1 Bước này chỉ đơn giản là chuyển một đĩa duy nhất từ cọc
If sodia>0 then begin
chuyen(sodia-1, CotNguon, CotTG, CotDich);
Writeln(CotNguon,'->',CotDich); { Dia lon nhat hien tai } chuyen(sodia-1, CotTG, CotDich, CotNguon)
Trang 19End;
End;
BEGIN
Write('Hay nhap so dia: '); Readln(n);
chuyen(n,'A','C','B');//Thực hiện chuyển từ cột A sang cột C với cột B làm trung gian
và khó khăn Có thể bạn sẽ nói rằng, vậy thì cứ sử dụng đệ quy, vừa ngắn gọn, dễhiểu, vừa dễ cài đặt Nhưng có đôi khi, sự hạn hẹp của bộ nhớ dành cho chươngtrình con không cho phép chúng ta làm điều đó, hoặc chúng ta biết rằng, ngôn ngữmáy không có đệ quy, vì vậy các trình biên dịch đều phải có nhiệm vụ khử đệ quy
Và một lí do nữa là bạn có thể thực sự gặp rắc rối với thủ tục đệ quy của mình khitrong một môi trường lập trình mà không cung cấp khả năng gọi đệ quy Khử đệquy giúp bạn vẫn giữ được nguyên bản thuật toán đệ quy của mình mà không hề
có lời gọi đệ quy, và như thế chương trình có thể chạy được trong bất kỳ môitrường lập trình nào
Khử đệ quy thực chất là chúng ta phải làm công việc của một trình biêndịch đối với một thủ tục, đó là: Đặt tất cả các giá trị của các biến cục bộ và địa chỉcủa chỉ thị kế tiếp vào ngăn xếp (Stack), quy định các giá trị tham số cho thủ tục
và chuyển tới vị trí bắt đầu thủ tục, thực hiện lần lượt từng câu lệnh Sau khi thủ
Trang 20tục hoàn tất thì nó phải lấy ra khỏi ngăn xếp địa chỉ trả về và các giá trị của cácbiến cục bộ, khôi phục các biến và chuyển tới địa chỉ trả về.
Các bước gợi ý trong việc khử đệ quy một cách tổng quát:
Chúng ta có thể tạo một ngăn xếp để chứa các bản ghi, lệnh gọi đệ quy và lệnh trả
về từ hàm đệ quy có thể được thay thế như sau, mỗi lệnh gọi đệ quy có thể đượcthay bởi:
1 Đưa vào ngăn xếp một bản ghi chứa các biến cục bộ, các thông số và vị trídòng lệnh ngay sau lệnh gọi đệ quy
2 Gán mọi thông số về các trị mới thích hợp
3 Trở về thực hiện dòng lệnh đầu tiên trong giải thuật đệ quy
4 Mỗi lệnh trả về của hàm đệ quy được thay bởi:
5 Lấy từ ngăn xếp để khôi phục mọi biến cục bộ và thông số
6 Bắt đầu thực hiện dòng lệnh tại vị trí mà trước đó đã được cất trong ngănxếp
3.2 Một số phương pháp khử đệ quy:
Trong thực tế các bài toán về đệ quy rất phong phú , không phải bài toán đệquy nào cũng đều có thể đưa về dạng khử đệ quy một cách chuẩn mực Nên việccài đặt các giải thuật khử đệ quy đòi hỏi phải hiểu rõ được tính chất đệ quy của bàitoán, trên cơ sở đó lựa chọn ra giải thuật phù hợp
Để thực hiện giải thuật khử đệ quy trong kĩ thuật lập trình ta có thể sử dụngthuật lặp, nhưng phổ biến là dùng cấu trúc dữ liệu kho đẩy (stack) để ghi nhớ đượccác bước xử lí, nhờ đó có thể phục hồi các bước xử lí trước Việc sử dụng stack đểthể hiện giải thuật khử đệ quy cũng y hệt như công việc mà một trình biên dịchphải làm khi dịch một chương trình đệ quy thành ngôn ngữ máy
3.2.1 Khử đệ quy bằng vòng lặp:
3.2.1.1 Hàm tính giá trị của dãy dữ liệu mô tả bằng hồi quy:
Ý tưởng:
Trang 21Xét một vòng lặp trong đó sử dụng một tập hợp biến W = ( V , U ) gồm tậphợp U các biến bị thay đổi trong vòng lặp và V là các biến còn lại.
Dạng tổng quát của vòng lặp là: W:=Wo ; {Wo = (Uo, Vo) }
While C(U) do U:=g(W) (1)
Gọi Uo là trạng thái của U ngay trước vòng lặp, Uk với k>0 là trạng thái của
U sau lần lặp thứ k (giả sử còn lặp đến lần k) Ta có:
Uo mang các giá trị được gán ban đầu
Uk =g(W) =g(Uk-1 ,Vo) =f( Uk-1 ) với k=1 n (2)
Với n là lần lặp cuối cùng, tức C(Uk) đúng với mọi k<n, C(Un) sai
Sau vòng lặp W mang nội dung (Un,Vo)
Ta thấy để tính giá trị dãy được định nghĩa bởi quan hệ hồi quy dạng (2) ta có thểdùng giải thuật lặp mô tả bởi đoạn lệnh (1)
Giải thuật tính giá trị của dãy hồi quy thường gặp dạng:
= g(n, f(n-1)) khi n > no
Vi dụ:
Xây dựng hàm FAC(n) = n! không đệ quy:
Function FAC (n: integer) : longint ;