Về đệ quy, nó cho phép giải quyết các bài toán phức tạp thông qua việc chia nhỏ vấn đề thành các bài toán con, từ đó giảm “sánh nặng” cho các lập trình viên.. Băng cách sử dụng kỹ thuật
Trang 1
HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG
KHOA VIÊN THÔNG I
BÀI TIỂU LUẬN MÔN TOÁN RỜI RẠC
Đề tài: Đệ quy và thuật toán quay lui
Nhóm bài tập: Nhóm 04
Đàm Đình Bảo Long Nguyễn Văn Chiến Ngô Thị Thu Huyền
Hà Nội, 2024
Trang 2
MỤC LỤC E90 0607 00010 1
5, Ưu, nhược điểm của đệ QUỊY 2 22t 2v 3E 23232123211 2121511 21111111111 ree 8
1.3 Đệ quy phi tuyến (Non-linear ReCurSiOn)) . :- 5-5222 2x+ccxvE2xsxexrrxrrsrrrsrrrrrrrree 10 1.4 Đệ quy làng (Nested Recursion)) 22c s2 v2 v2 211212151 11212111.21111 xe 11
2 Đệ quy gián tiếp - - Q-TtTn2v vn T22 1221511121111 1111111111111 1.1111.111 re 11 2.1 Đệ quy gián tiếp hai ChiỀU à 02 2222522 2x2x22 21222121 1E 121211 erree 12 2.2 Đệ quy gián tiếp nhiều ChiÀMU 2-5252 222t 2222x222 EEEkrkrrrerrrrrrrreo 12 li 2 0 13
Trang 3BB VEU cecccccseccsccsssesssecssevssevessusssueesevssavessessuessaessvessusssussssvssaessuessusssetsvsvessessutesetesevesseesseseees 18
3.4 ĐặC điỂm 03 ST 1 11111121 EE1 1111112111111 T111 ro 18
2 BFS/DFS Q.2 L1 212 011112111011012111011111111011111111211111111211111111 1111111111111 nga 18 2.1 Tìm kiếm theo chiều rộng (Breadth-first Search-BFS) ào ee 18 2.2 Tìm kiếm theo chiều sâu (Depth-first Search-DFS) coi 19
3 Quy hoạch động (Dynamic Programming - DP) SH HH 20 kh 20 À2 1 4 n8 .ẻằ.e 20
Trang 4LOI MO DAU
Ngày nay, công nghệ thông tin đang phát triển một cách mạnh mẽ, vượt bậc Đề không bị tụt lại so với thời đại, việc nắm vững kỹ năng cơ ban vẻ lập trình là vô cùng cân thiết Trong đó, hai khái niệm nổi bật trong lập trình hiện nay là Đệ quy và Thuật toán quay lui (backtracking) Hai khái niệm này không chỉ là những công cụ mạnh mẽ trong việc giái quyết các bài toán mà còn là những khái niệm cơ bản trong tư duy giai quyét van dé
Về đệ quy, nó cho phép giải quyết các bài toán phức tạp thông qua việc chia nhỏ vấn đề thành các bài toán con, từ đó giảm “sánh nặng” cho các lập trình viên Còn với thuật toán quay lui là một phương pháp hiệu quả đề tìm kiếm và giải quyết các bài toán tối ưu và tìm nghiệm, đặc biệt hữu ich trong các bài toán tổ hợp Băng cách sử dụng kỹ thuật quay lui, chúng ta có thế tìm kiếm các giải pháp một cách có hệ thống và loại bỏ những lựa chọn không kha thi, từ đó tối ưu hóa quá trình giải quyết van dé
Bài tiêu luận này sẽ giải thích bản chất và cơ chế hoạt động của đệ quy, phân loại, nêu ứng dụng của đệ quy Sau đó, chuyến sang việc phân tích thuật toán quay lui và cách thức ứng dụng của nó trong các bài toán thực tế Chúng ta sẽ xem xét ví dụ cụ thé, qua đó, từ đó giúp nâng cao hiểu biết về đệ quy và thuật toán quay lui
Trang 5L Sơ lược về đệ quy
1 Giới thiệu khái niệm đệ quy
Đệ quy là một phương pháp giải quyết vấn đề, trong đó nó sử dụng các trường hợp ví đụ đơn gián hơn của vấn đề đề truy hồi, từ đó có thé giải quyết các vấn đẻ phức tạp hơn
Trong khoa học máy tính, khái niệm đệ quy là một phương pháp giải toán mà trong đó lời giải của bài toán phụ thuộc vào một trường hợp nhỏ hơn của cùng một bài toán đó Trong lập trình, hàm đệ quy được nhận biết đơn giản là việc trong code thực thị hàm có chứa lời gọi đến chính nó
2 Cấu tạo cơ bản của đệ quy
Cấu tạo cơ bán của đệ quy gồm 2 phần: trường hợp cơ bán (base case) và trường hợp đệ quy (recursive case)
2.1 Trưởng hợp cơ bán của đệ quy - base case
Truong hop co ban (base case) của đệ quy là thành phần nhỏ nhất trong đệ quy, là trường hợp
mà bài toán đã được giải quyết mà không cần phái gọi lại chính nó Phần này thường là các trường hợp cụ thế, như x == 0, x == n Bản chất cái tên "base" cũng đã ám chỉ việc nó là nền móng quan trọng nhất trong đệ quy, nơi mà các bài toán khác cần phải sử dụng đến
Mục tiêu của base case là tìn một điểm dừng cho đệ quy, vì nếu không có điểm đừng này, đệ quy sẽ bị chạy đến vô hạn số lần
2.2 Trwong hep dé quy - recursive case
Truong hop dé quy (recursive case) của đệ quy là thành phân phức tạp hơn base case, do đó,
nó cần thực hiện liên tiếp các hành động gọi lại để tìm ra lời giải, cho đến khi gol dén base case Việc recursive case gọi liên tiếp gọi lại chinh no nham tién gan dén base case, déng thoi giai quyét một bài toán nhỏ hơn so với bài toán ban đầu, cho đến khi gọi đến base case
Mục tiêu của recursive case là có gắng tìm ra một bài toán nhẹ nhàng, dễ giải quyết hơn cho đến khi đạt đến điểm dừng là base case
Trang 6e HÀMTÊN_ HÀM(tham số): là cách để định nghĩa một hàm với tên và tham só
dừng đệ quy hay không
e TRA VE gia tri dừng: là giá trị sẽ được trả về khi điều kiện dừng thỏa mãn
e NGƯỢC LẠI: chỉ ra phản xử lý khi điều kiện dừng không thỏa mãn
e TRẢ VẼ biếu thức bao gồm TÊN_HÀM(tham số đã thay đổi): gọi lại chính hàm với tham số đã thay đồi
- Ví dụ áp dụng: Với số tự nhiên n cho trước, tinh n!
3
Trang 7e Trong C++:
* Phan tich ma:
1 Dinh nghia ham factorial: int factorial(int n) {
int là kiểu trả về của hàm
£actoria1 là tên của hàm, int n là tham số đầu vào
2 Điều kiện đừng: i£ (n == 0) {
Nếu n không bằng 0, hàm sẽ gọi chính nó với tham số n - 1, và nhân kết quả với
n Đây là bước đệ QUY
4 Giá trị trả về:
Hàm trả về kết quá Của phép nhân giữa n và giá trị trả về của lời gọi đệ quy Khi
điều kiện dừng được đạt tới, các giá trị bát đầu trở về và được tính toán dân dẫn
Trang 8£actoria1 là tên của hàm, và n là tham số đầu vào
2 Điều kiện dừng: ¡£ n ==
Là câu lệnh điều kiện kiếm tra xem n có bằng 0 không Nếu điều kiện đúng (n bằng 0), hàm sẽ trả về giá trị 1 Day là điều kiện dừng của hàm, ngăn không cho hàm gọi chính nó
vô hạn
3 Lời gọi đệ quy:
else: xác định phần còn lại của hàm nếu điều kiện dừng không được thỏa mãn (n
Hàm trả về kết quá Của phép nhân giữa n và giá trị trả về của lời gọi đệ quy Khi
điều kiện dừng được đạt tới, các giá trị bát đầu trở về và được tính toán dân dẫn
* Vị dụ hoạt động:
Nếu gol factoria1 (3), quá trình sẽ như sau:
factorial (3) Sẽ Qọi 3 * £actorial (2)
factorial (2) Sẽ Qọi 2 * £actorial (1)
£actorial (1) Sẽ QọÌ1 * £actorial (0)
factorial (0) sé tra vé 1 (diéu kién ding)
Khi quay trở lại:
4.1 Thuật foán tìm kiếm và sắp Xếp
Trong thuật toán tìm kiếm, hàm đệ quy có thê được sử dụng đề tìm kiếm các phần tử trong một mảng theo cách đệ quy như sau:
Trang 9THUẬT TOÁN BINARY SEARCH
Tìm kiếm nhị phân là một thuật toán tìm kiếm hiệu quả trên các máng đã được sắp xếp Trong thuật toán này, danh sách được chia nhỏ thành các phan bang nhau và sau đó kiểm tra xem giá trị tìm kiếm có trong nửa phần nào Quá trình này được lặp lại trên nửa phần tương ứng cho đến khi tìm thấy phần tử hoặc xác định răng phần tử không tôn tại trong danh sách
b Tìm kiếm đường đi (Path Finding)
Trong tìm kiếm đường đi trên đỏ thị, đệ quy có thê được sử dụng đề đuyệt các đỉnh và cạnh của
đề thị để tìm đường đi từ một đỉnh đến đỉnh khác Thuật toán nhự Depth-First Search (DFS) và Breadth-First Search (BFS) thường được triển khai bằng đệ quy
c Sap xép merge (Merge sort)
Trang 10d Sap xép nhanh (Quick sort)
arrf[lE 10 30 | 40 | 90 80
⁄
10 | 30 | 90 | 80
Recursively call quickSort for left portion (from low to pi - 1) and right portion
(from pi + 1 to high) of the array to sort the elements around pivot
Quick sort là thuật toán sắp xếp chọn phân hoạch như một phần tử chốt, sử dụng đệ quy đề sắp xếp các phần nhỏ hơn và lớn hơn phần tử chốt, sau đó kết hợp chúng lại với nhau
4.2 Thuật đoán trên cây (free) và đồ thị (graph)
Trong thuật toán trên cây và đồ thị, hàm đệ quy có nhiều ứng dụng quan trọng, bao gồm:
a Duyét cdy (tree traversal)
Inorder: 4, 2, 1, 7, 5, 8, 3, 6
Duyệt các nút trong cây (như cây nhị phân, cây tìm kiếm, cây cân bằng) thường được thực hiện bằng cách sử dụng hàm đệ quy Các phương pháp đuyệt như pre-order (tiền thứ tự), in-order (trung thứ tự) và post-order (hậu thứ tự) đều dựa trên kỹ thuật đệ quy đề duyệt qua các nút theo thứ tự mong muốn
b Từm kiếm trên cây và đồ thị
Trong việc tìm kiếm phần tử trên cây hoặc đỏ thị, đệ quy có thế được sử dụng để duyệt qua các nút hoặc đỉnh một cách cần thiết đề tìm kiếm phần tử hoặc đường đi Các thuật toán tìm kiếm như Depth-First Search (DFS) va Breadth-First Search (BFS) thường được triển khai theo cách sử dụng
đệ quy
Trang 11c Quán jý cẩu trúc đữ liệu đệ quy
Trong việc thiết kế và quan ly cầu trúc dữ liệu phức tạp như cây và đồ thị, việc sử dụng hàm đệ quy giúp dễ dàng triển khai các thao tác thêm, xóa và đuyệt một cách logic và hiệu quả 4.3 Ứng dựng quy hoạch động
Trong quy hoạch động, hàm đệ quy được sử dụng đề giải quyết các vấn để tối ưu hoá bằng cách tận dụng tính chất tái lập và ghi nhớ kết quả của các bài toán phụ Cụ thé, ứng dụng của hàm đệ qui trong quy hoạch động bao gồm:
a Tim kiém dé quy (Recursive search)
Trong bài toán quy hoạch động, việc tìm kiếm các cách giai quyết tối ưu thường được thực hiện
đệ quy Thuật toán sẽ thăm dò các khá năng và ghi nhớ các lời giải tối ưu của các bài toán nhỏ hơn
b Tố: lời giái (Optimal solution)
c Ghi nhớ kết quá (Memoization)
Đệ quy trong quy hoạch động thường được kết hợp với kỹ thuật ghi nhớ kết quả đề tránh tính toán lại các kết quả đã biết
5, Ưu, nhược điểm của đệ quy
5.1 Ưu điểm
a Giảm độ phúc tạp của mã nguồn
Đôi khi, sử đụng đệ quy có thể giúp giảm độ phức tạp của mã nguồn so với việc sử đụng vòng lặp Điều này làm cho mã nguồn trở nên ngắn gọn và để nhìn hơn
b Có lợi cho các vấn đề có cấu trúc đệ QUY
Nếu vấn đề tự nhiên có tính chất đệ quy (ví dụ như cây, danh sách liên kết, hoặc các cấu trúc đữ liệu đệ quy), việc triển khai thông qua đệ quy thường là lựa chọn tự nhiên và để đàng hơn
c Thun tiện các vấn đề chia nhỏ
Khi một vấn đề lớn có thế được chia nhỏ thành các vấn đề con có cùng cấu trúc như vấn đề gốc,
đệ quy là một lựa chọn tự nhiên cho việc giải quyết vấn đề đó
d Hiệu suát (trong mót số zzzờng hợp)
Mặc dù đệ quy có thể gặp vấn để vẻ hiệu suất do chi phi của việc gọi hàm đệ quy và lưu trữ trong ngăn xép, nhưng trong một số trường hợp, thuật toán đệ quy có thê để dàng và hiệu quá hơn
so với cách giải không sử dụng đệ quy
5.2 Nhược điểm
Trang 12a Sứ dụng quá nhiều bộ nhớ
Mỗi lần gọi hàm đệ quy, trình thông dịch hoặc trình biên dịch cần phái giữ lại thông tin về các lời gọi hàm trước đó trên stack Điều này có thê dẫn đến việc sử dụng một lượng lớn bộ nhớ, đặc biệt là với các đệ quy sâu Vì vậy, cần phái phân tích bài toán nếu sử dụng đệ quy sâu có thê dẫn tới ngồn tài nguyên máy tính quá nhiều thì không nên dùng
b Hiéu sudt co thé cham
Các hàm đệ quy có thê chậm hơn so với các vòng lặp tương đương đo overhead (quá tải) từ việc gọi hàm Điều này là đo đệ quy gọi lại hàm của chính nó và với số lượng gọi hàm lại quá nhiều khiến quá tải
c Rái ro về lỗi
Đệ quy không đúng cách có thê dẫn đến lỗi tran stack hoặc lỗi vô hạn đệ quy Do đó, cần thử
đệ quy với đầu vào là cấp số nhỏ, hoặc thậm chí có điều kiện bắt lỗi kiểm tra xem đầu vào có giá trị quá lớn hay không
d Khó hiểu và debug
Đối với những người mới học lập trình hoặc những người không quen với đệ quy, việc hiểu và debug code đệ quy có thế trở nên khá phức tạp Cách thông thường hiểu đệ quy đó nên sử dụng lệnh in ra giá trị biến và hàm trả về ở mỗi bước
e Không tối ưu cho tất Cả các nên tảng
Một số hệ thông hoặc nền táng có giới hạn về kích thước của stack, làm cho việc sử dụng đệ quy trở nên không phù hợp Trong một số trường hợp, giải thuật đệ quy có thế được tối ưu hơn bằng cách sử dụng các kỹ thuật khác như memoization, nhưng việc này có thê thêm phức tạp vào code
II Phan loại đệ quy
Đệ quy chủ yếu có hai loại tùy thuộc vào việc một hàm gọi chính nó từ bên trong nó hay nhiều hàm gọi lẫn nhau Loại đầu tiên được gọi là đệ quy trực tiếp và loại còn lại được gọi là đệ quy gián tiếp Do đó, đệ quy được chia làm hai loại chính: đệ quy trực tiếp và đệ quy gián tiếp
1 Đệ quy trực tiếp
Đệ quy trực tiếp có thế phân loại thành 4 loại:
1.1 Đệ quy tuyén tinh (Linear Recursion)
- Dé quy tuyén tinh (Linear Recursion) la mét ky thuat lập trình nơi một hàm gọi lại chính nó một cách trực tiếp, nhưng chỉ thực hiện một lần trong mỗi lần gol
Trang 13- Cấu trúc: là dạng đệ quy có cấu trúc đơn giản nhất trong đệ quy khi nó luôn gọi lại chính nó
cho mỗi lần thực hiện cho đến khi tìm được base case
¢ Base Case: Diéu kién co ban dé két thúc quá trình đệ quy Nếu không có base case, ham sé tiép tục gọi chính nó vô tận
hơn hoặc đơn giản hơn
- Phân tích:
© Space Complexity: Trong đệ quy tuyến tính, độ phức tạp không gian (space complexity) thường là O(n) vi cé n lời gọi hàm được lưu trữ trên stack
e _ Time Complexity: Độ phức tạp thời gian (time complexity) cũng là O(n) vì mỗi lần
đệ quy, độ phức tạp về tính toán sẽ giảm đi một lượng có định
1.2 Đý quy nhề phân (Binary Recursion)
- Đệ quy nhị phân (Binary Recursion) là kỹ thuật lập trình mà trong đó mỗi hàm gọi lại chính
nó hai lần trong mỗi lần thực thi
- Cầu trúc:
¢ Base Case: Diéu kién co ban dé két thúc quá trình đệ quy, tương đối giống với đệ quy tuyến tính
hai lần, thường với đối số khác nhau
- Phân tích:
e Space Complexity: Trong đệ quy nhị phân, độ phức tạp không gian (space complexity) thường là O(n), đo kiểu đệ quy này lưu trữ một thông tin dưới đạng cây nhị phân
e _ Time Complexity: Độ phức tạp thời gian là O(2^n), biểu diễn cho số lượng lời gọi hàm tổng cộng mà ở đây là hai lần Vi time complexity trén là cực kỳ lớn, do đó rất hiểm trường hợp mà chúng ta sử dụng kiểu đệ quy này trong thực tế
1.3 Đệ quy phi tuyến (Non-linear Recursion)
- Trong đệ quy phi tuyến, số lần một hàm gọi lại chính nó có thể thay đổi và không có định, nó
có thế phụ thuộc vào nhiều yếu tô khác nhau như giá trị đầu vào, điều kiện trong hàm
- Cầu trúc:
¢ Base Case: Diéu kién co ban dé két thúc quá trình đệ quy, tương đối giống với đệ quy tuyến tính
10