Professional Documents
Culture Documents
Recursion
Recursion
3
Ví dụ: factorial
4
Hàm đệ quy
• Một lời giải đệ quy luôn bao gồm 2 giai đoạn
• Giai đoạn đệ quy: khi trường hợp cơ sở chưa thỏa mãn
• Giai đoạn này sẽ được thực hiện cho đến khi đi đến trường hợp cơ sở
• Giai đoạn cơ sở: Các hàm được gọi đệ quy sẽ trả về giá trị của
chúng cho các lời gọi đệ quy trước đó
• Hàm cuối cùng trả về giá trị cho hàm cuối thứ 2, hàm cuối thứ 2 trả về giá
trị cho hàm cuối thứ 3, …
• Cuối cùng, nó đạt đến hàm đầu tiên và tính được giá trị cuối cùng
5
Ví dụ: factorial
Lời giải dùng đệ quy cho hàm Factorial Lời giải dùng vòng lặp cho hàm Factorial
long factorial(int k) { long factorial(int k) {
if (k == 0) long t = 1;
return 1; for (int j = 2; j <= k; j++)
else t *= j;
return k * factorial(k-1); return t;
} }
8
Ví dụ: Tính số Fibonacci
• Fibonacci
• Fibo(n) = C(n-1) + C(n-2)
• Fibo(1) = Fibo(2) = 1
• Lời giải đệ quy
int fibo(int n) {
if (n <= 2)
return n;
else
return fibo(n-1) + fibo(n-2);
}
9
Ví dụ: Tính fibo(5), ta sẽ viết f(5) cho gọn
f(5)
return f(4) + f(3)
f(4) f(3)
return f(3) + f(2) return f(2) + f(1)
f(2) f(1)
return 1 return 1
10
Ví dụ: Tính tổ hợp (Combinatorial)
• Tính số cách chọn k phần tử từ n phần tử
• C(k, n) = C(k-1, n-1) + C(k, n-1) Chọn phần tử đầu tiên Chọn k-1 từ n-1 phần tử
• C(0, n) = C(n, n) = 1
Chọn k từ n phần tử
• Lời giải đệ quy
int comb(int k, int n) { Không chọn phần tử đầu tiên Chọn k từ n-1 phần tử
if (k > n) return 0;
if (k == n || k == 0) return 1;
return comb(k-1, n-1) + comb(k , n-1);
}
11
Ví dụ: Tính C(3, 4)
C(3, 4)
return C(2, 3) + C(3, 3)
C(2, 3) C(3, 3)
return C(1, 2) + C(2, 2) return 1
C(1, 2) C(2, 2)
return C(0, 1) + C(1, 1) return 1
C(0, 1) C(1, 1)
return 1 return 1
12
Ví dụ: Tháp Hà Nội (Tower of Hanoi)
• Ta muốn di chuyển tất cả đĩa từ cột 1 (nguồn) sang cột 3 (đích), dùng
cột 2 như cột tạm
• Mỗi lần chỉ di chuyển một đĩa
• Mỗi đĩa không được nằm trên đĩa nhỏ hơn
13
Tower of Hanoi – Lời giải đệ quy
14
Tower of Hanoi – Lời giải đệ quy
void tower(int n, char s, char d, char t) {
if (n == 1)
move(s, d);
else {
tower(n-1, s, t, d);
move(s, d);
tower(n-1, t, d, s);
}
}
void move(char s, char d) {
cout << "move from " << s << " to " << d << endl;
}
15
Tóm tắt
• Đệ quy là một cách tiếp cận để mạnh mẽ để thiết kế lời giải và giải
quyết vấn đề
• Một hàm đệ quy có phần cơ sở và phần đệ quy
• Lời giải đệ quy thường gọn gàng và tinh tế nhưng có thể không hiệu
quả do có thể có nhiều lời gọi lặp lại
• Lời giải dùng vòng lặp thường hiệu quả hơn lời giải đệ quy nhưng có
thể khó hiện thực và khó hiểu hơn
16