Võ Quang Hoàng Khang
1
Cho S(n) = 1 + 2 + 3 + … + n =>S(10)? S(11)?
2
3
Một hàm được gọi có tính đệ quy nếu trong thân của hàm đó có lệnh gọi lại chính nó.
Ví dụ S(n) được tính thông qua S(n-1)
2 điều kiện quan trọng Tồn tại bước đệ quy. Điều kiện dừng.
4
B1. Tham số hoá bài toán. B2. Phân tích trường hợp chung: đưa bài toán về dạng bài toán cùng loại nhưng có phạm vi giải quyết nhỏ hơn theo nghĩa dần tiến đến trường hợp suy biến.
B3. Tìm trường hợp suy biến.
5
Hàm đệ quy gồm 2 phần:
Phần cơ sở: Điều kiện để thoát khỏi đệ quy
(điểm dừng)
Phần đệ quy: gọi đến chính nó với giá trị mới
Ví dụ:
của tham số nhỏ hơn giá trị ban đầu.
6
• Công thức truy hồi tính
• Hàm đệ quy: long GiaiThua( int n ) {
if(n==0)
return 1;
else
return GiaiThua(n-1)*n;
7
}
• Hàm đệ quy nhập mảng 1 chiều:
void NhapMang(int a[],int n) {
if(n>0) {
NhapMang(a,n-1); cin>>a[n-1];
}
8
}
9
Trong thân hàm có duy nhất 1 lời gọi hàm gọi lại chính nó một cách tường minh.
if (điều kiện dừng) {
//Trả về giá trị hay kết thúc công việc
}
//Thực hiện các công việc (nếu có)
. . . TenHam (
}
10
Ví dụ 1: Tính Điều kiện dừng: S(0) = 0. Công thức truy hồi: S(n) = S(n-1) + n.
if(n==0) //điểm dừng
int TongS (int n) {
return 0;
return ( TongS(n-1) + n );
}
11
Ví dụ 2: Tính n!
long GiaiThua(int n)
if (n==0)
//điểm dừng
{
return 1;
return n*GiaiThua(n-1);
else
}
với n=5
12
if (điều kiện dừng) {
//Trả về giá trị hay kết thúc công việc
}
//Thực hiện các công việc (nếu có)
. . . TenHam (
}
Trong thân hàm có 2 lời gọi hàm gọi lại chính nó một cách tường minh.
13
Ví dụ: Tính số hạng thứ n của dãy Fibonaci được định nghĩa f0=f1=1 ; bởi công thức truy hồi: fn = fn-1 + fn-2 ; (n>1)
Điều kiện dừng: f(0) = f(1) = 1.
long Fibonaci(int n) {
if(n==0 || n==1)
return Fibonaci(n-1)+ Fibonaci(n-2);
return 1;
}
14
Trong thân của hàm có lời gọi hàm gọi lại chính nó được đặt bên trong vòng lặp.
for (int i = 1; i<=n; i++) {
//Thực hiện một số công việc (nếu có) if (điều kiện dừng) { . . .
//Trả về giá trị hay kết thúc công việc
} else {
//Thực hiện một số công việc (nếu có)
TenHam ();
}
}
15
}
Ví dụ: Tính số hạng thứ n của dãy {Xn} được định nghĩa như
sau: X0 =1 ;
Xn = n2X0 + (n-1)2X1 + … + 12Xn-1 ; (n≥1)
Điều kiện dừng: X(0) = 1.
if(n==0)
long TinhXn(int n) {
return 1; long s = 0; for (int i=1; i<=n; i++)
s = s + i * i * TinhXn(n-i);
return s;
16
}
Trong thân của hàm này có lời gọi hàm đến hàm kia và ngược lại.
17
//Thực hiện một số công việc (nếu có)
…TenHam2 ();
//Thực hiện một số công việc (nếu có)
}
//Thực hiện một số công việc (nếu có)
…TenHam1 (
}
18
(n>0)
Ví dụ: Tính số hạng thứ n của hai dãy {Xn}, {Yn} được định nghĩa như sau: X0 =Y0 =1 ; Xn = Xn-1 + Yn-1; Yn = n2Xn-1 + Yn-1; (n>0)
- Điều kiện dừng: X(0) = Y(0) = 1.
long TinhYn(int n); long TinhXn (int n) {
if(n==0)
return 1;
return TinhXn(n-1) + TinhYn(n-1);
} //---------------------------------------------------------------------- long TinhYn (int n) {
if(n==0)
return 1;
19 return n*n*TinhXn(n-1) + TinhYn(n-1);
}
Thay vì sử dụng lời giải đệ quy cho một bài toán, ta có thể thay thế bằng lời giải không đệ quy (khử đệ quy) bằng phương pháp lặp.
Ưu và khuyết điểm của đệ quy:
Ưu điểm
Khuyết điểm
Thuận lợi cho việc biểu diễn bài toán Gọn (đối với chương trình)
Có khi không được tối ưu về thời gian Có thể gây tốn bộ nhớ
Trong lập trình HẠN CHẾ viết hàm đệ quy nếu thấy không
cần thiết.
20
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
21
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
22
Ví dụ 3: Bài toán tháp Hà Nội
Chuyển một chồng n đĩa với kích thước khác nhau từ cột A sang cột C theo nguyên tắc:
Mỗi lần chỉ chuyển 1 đĩa. Không được đặt đĩa lớn trên
đĩa nhỏ.
Có thể dùng cột B làm cột
trung gian B
23
* Tham số hoá bài toán: HaNoi (n, A, B, C) n: Số đĩa.
Trong đó:
A: Cọc nguồn
B: Cọc trung gian
C: Cọc đích
(A, B, C có kiểu ký tự)
24
Giải thuật đệ quy bài toán Tháp Hà Nội: * Trường hợp suy biến:
Nếu n = 1 thì chuyển đĩa từ A qua C
* Trường hợp chung (n 2):
Thử với n=2:
+ Chuyển đĩa thứ nhất từ A sang B
+ Chuyển đĩa thứ hai từ A sang C
+ Chuyển đĩa thứ nhất từ B sang C
Tổng quát:
+ Chuyển (n -1) đĩa từ A sang B (C làm trung gian)
+ Chuyển 1 đĩa từ A sang C (B làm trung gian)
+ Chuyển (n -1) đĩa từ B sang C (A làm trung gian)
25
1 đĩa
B
C
A
1 đĩa
B
C
A
2 đĩa
B
C
A
2 đĩa
B
C
A
2 đĩa
B
C
A
2 đĩa
B
C
A
N đĩa
B
C
A
N đĩa
B
C
A
N đĩa
B
C
A
Giải thuật đệ quy bài toán Tháp Hà Nội:
void HaNoi (int n, char A, char B, char C) {
if (n==1)

