Tải bản đầy đủ (.pdf) (10 trang)

Giải thuật đệ quy

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (175.25 KB, 10 trang )

Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................-
133






Chương 5

Giải thuật ñệ quy




Nội dung của chương này ñề cập ñến những bài toán có tính ñệ quy. Không phải bài
toán nào cũng có tính ñệ quy và không phải các bài toán có tính ñệ quy thì ñều phải giải bằng
giải thuật ñệ quy. Các vấn ñề cần quan tâm trong chương này:
 Bài toán có tính ñệ quy không
 Có cần dùng giải thuật ñệ quy không
 ðệ quy có mang lại hiệu quả hơn các phương pháp thông thường hay không

Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................-
134

1. Khái niệm ñệ quy

Trong thân một chương trình con có thể ñưa lời gọi tới chính chương trình con ñó, tính
chất này ñược gọi là tính "ðệ qui của chương trình con".
Trong toán học khái niệm giai thừa ñược ñịnh nghĩa như sau:
0! = 1


Nếu n > 0 thì n! = 1*2*3*...*n
Từ ñịnh nghĩa trên dễ dàng thấy rằng
n! = n*(n-1)!
(n-1)! = (n-1)*(n-2)!
......
1! = 1*0! =1

Cách thức lập luận như trên ñưa chúng ta tới một nhận xét tổng quát là: lời giải của bài
toán A có thể ñược thực hiện bởi lời giải của bài toán A' có dạng giống như A. Thật vậy, việc
tính n! có thể ñược thực hiện bởi việc tính (n-1)!.
ðiều quan trọng ñể bài toán có lời giải là tuy A' giống như A song thực chất A' phải
nhỏ hơn A và quá trình "thu nhỏ" phải có ñiểm dừng. Trong bài toán tính giai thừa từ chỗ cần
tính giai thừa của n chúng ta ñi tính giai thừa của (n-1), ñể tính giai thừa của (n-1) chúng ta ñi
tính giai thừa của (n-2)... kết thúc là giai thừa của 0.
Một ñối tượng ñược gọi là ñệ quy nếu nó ñược ñịnh nghĩa dưới dạng của chính nó.
Giải thuật của bài toán A ñược gọi là ñệ quy nếu nó dẫn tới việc giải bài toán A' giống
như A nhưng nhỏ hơn A và quá trình phải có ñiểm dừng.

Xét bài toán tính giai thừa với n = 5:

Ô nhớ cuối 1! = 1
2! = 2*1!
3! = 3*2!
4! = 4*3!
Ô nhớ ñầu 5! = 5*4!

Hình 5.1

Như vậy khi biết 1! thì tính ñược 2!, biết 2! Thì tính ñược 3!,...
Bằng cách sử dụng bộ nhớ ngăn xếp theo nguyên tắc LIFO ( Last In - First Out) (Hình

1.3) những gì gửi vào cuối cùng thì ñược lấy ra trước tiên. Bóc ô nhớ trên ñỉnh ta có 1! = 1 và
lộ ra ô tiếp theo 2! = 2*1!. Vì 1! ñã biết nên tính ñược 2! = 2, bóc tiếp ô nhớ phía dưới ta có
3! = 3*2!, vì 2! ñã biết nên 3! = 3*2 = 6 quá trình tiếp tục cho ñến khi bóc ô nhớ dưới cùng và
chúng ta nhận ñược 5! = 120. Dưới ñây là chương trình tính giai thừa

5! = 5*4!
4! = 4*3!
3! = 3*2!
2! = 2*1!
1! = 1

Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................-
135

Ví dụ 5.1:
Program Giaithua;
Uses crt;
Var n: integer;
Function GT(m: integr): integer; (* Hàm GT tính giai thừa của n*)
Begin
if m=0 then GT:=1 else GT:= m*GT(m-1); (*Gọi ñệ qui của GT *)
End;
Begin
Clrscr;
write ('Tinh giai thua cua n = '); Readln (n) (*ðọc giá trị n*)
write('Gia thua cua ',n, ' = ',GT(n)); (* Viết giá trị hàm GT *)
Repeat until keypressed;
End.

Ví dụ 5.1 có một số ñiều ñáng lưu ý sau ñây:

1. Hàm GT ñược xây dựng ñể tính giai thừa với tham số hình thức m, kiểu của m là kiểu
Integer. Giá trị m sau này sẽ ñược thay thế bằng tham số thực n qua lời gọi GT(n) trong
chương trình mẹ.
2. Khi ñịnh nghĩa kiểu của GT là Integer thì giá trị của n chỉ ñược chọn nhỏ hơn 8 vì 8!
= 40320 vượt quá giá trị cực ñại của Integer (32767). ðể có thể tính giai thừa với n>=8 ta phải
ñịnh nghĩa function GT có kiểu Longint hoặc Real. Với kiểu Real lệnh viết giá trị của giai
thừa phải là viết số thực với phần lẻ bằng 0, ví dụ:
Write (GT(n):12:0);
3. Sử dụng thuật toán ñệ quy ñồng nghĩa với việc phải xây dựng chương trình con, vì
vậy nếu sử dụng các vòng lặp có thể giải ñược bài toán thì nên dùng vòng lặp. Trừ trường hợp
bắt buộc phải giải bài toán không có tính lặp hoặc bài toán có khả năng truy hồi.
Với bài toán tính giai thừa có thể dùng vòng lặp và chúng ta thấy chương trình sẽ ñơn
giản hơn nhiều so với cách dùng tính ñệ quy:

Ví dụ 5.2
Program Tinh_GT;
Uses crt;
Var i,n:byte; gt:longint;
Begin
Clrscr;
Write(' Nhap gia tri n '); Readln(n);
if (n = 0) or (n=1) then gt:=1;
if n > 1 then gt:=1;
For i:= 1 to n do gt:=gt*i;
Writeln('Giai thua cua ',n,' = ',gt);
Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................-
136

Readln;
End.


Ví dụ 5.3: Lập chương trình tìm ước số chung lớn nhất của hai số nguyên n, m.
Ước số chung lớn nhất của hai số n và m tính theo công thức :
n nếu m = 0
USC(n,m) =
USC(m, n mod m ) nếu m <> 0

Ví dụ n= 4, m=8
USC(4,8) = USC(8, 4) = USC(4,0) = 4
Chương trình ñược xây dụng như sau:

Program timUSC ;
Uses crt;
Var n,m : word; Lam: Char;
FUNCTION USC(a,b:word): word;
Begin
If b=0 then USC := a Else USC := USC(b,a mod b);
End;
BEGIN
Repeat
Clrscr;
Write(' Hay cho hai so "n" va "m" can tim uoc so chung ');
Readln(n,m);
Writeln(' Uoc so chung lon nhat cua ',n,' va ',m, ' la ',USC(n,m):5);
Writeln;
Write('Tim tiep hay thoi ? C/K '); read(lam);
Until Upcase(lam)='K';
END.

Bài toán kinh ñiển ứng dụng giải thuật ñệ quy là bài toán Tháp Hanoi. Nội dung bài

toán như sau:
Có n chiếc ñĩa tròn ñường kính khác nhau, các ñĩa có lỗ ở giữa. Người ta xếp lồng các
ñĩa này vào một cọc theo thứ tự trên nhỏ dưới to. Yêu cầu phải xếp các ñĩa này sang cọc mới
theo nguyên tắc:

1. Mỗi lần chỉ ñược chuyển 1 ñĩa
2. Không ñược ñể xảy ra tình trạng ñĩa to ở trên, ñĩa nhỏ ở dưới dù là tạm thời
3. ðược phép dùng một cọc trung gian
Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................-
137


Giả sử cọc ñầu tiên là cọc A, cọc trung gian là B và cọc cần xếp ñĩa sang là cọc C.
Chúng ta sẽ xét một số trường hợp ñơn giản ñể tìm quy luật (Hình 5.2)
* n =1: cọc A chỉ có một ñĩa
Chuyển ñĩa từ cọc A sang cọc C
Kết thúc






A B C

Hình 5.2

* n = 2: cọc A có 2 ñĩa (Hình 5.3)
Chuyển ñĩa trên sang B
Chuyển ñĩa dưới sang C

Chuyển ñĩa từ B sang C
Kết thúc









A B C C

Hình 5.3
* n = 3: cọc A có 3 ñĩa
Với trường hợp 3 ñĩa nếu chúng ta coi 2 ñĩa trên là một ñĩa thì bài toán quy về trường
hợp n = 2, khi ñó lời giải sẽ là: (Hình 5.4)
Chuyển 2 ñĩa trên sang B
Chuyển ñĩa dưới cùng sang C
Chuyển 2 ñĩa từ B sang C
Kết thúc

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×