Một thủ tục đệ qui gồm có hai phần chính
Phần cố định (neo): gía trị khởi đầu cho hàm, thủ tục đệ qui.
Phần hạ bậc (phần đệ qui): Tác động của hàm đệ qui được thực hiện thông qua tác động hay giá trị đã được định nghĩa trước.
Phân tích giải thuật đệ qui tính giai thừa:
f(3)->f(2)->f(1)->f(0)->1
-> như vậy để tính 3! Hàm f được gọi 4 lần.
Phân tích Fibonacci:
15 trang |
Chia sẻ: haohao89 | Lượt xem: 3035 | Lượt tải: 0
Bạn đang xem nội dung tài liệu Bài giảng Đệ quy, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Đệ quy 1. Khái niệm về đệ quy Ta nói một đối tượng là đệ qui nếu đối tượng này bao gồm chính nó như một bộ phận hoặc đối tượng được định nghĩa dưới dạng của chính nó. Ví dụ 1: số tự nhiên + 1 là một số tự nhiên + n là một số tự nhiên nếu n-1 là một số tự nhiên Ví dụ 2: giai thừa + 0!=1 + n !=n*(n-1) ! 2. Giải thuật đệ qui và thủ tục đệ qui Nếu lời giải của bài toán T được thực hiện bằng lời giải của một bài toán T’, có dạng giống như T, thì đó là một lời giải đệ qui. Giải thuật tương ứng với lời giải như vậy gọi là giải thuật đệ qui. Trong thủ tục có lời gọi đến chính nó gọi là thủ tục đệ qui. 3. Thiết kế giải thuật đệ quy bài toán được định nghĩa dưới dạng đệ qui thì ta rất dễ thiết kế giải thuật đệ. Ví dụ 1 : Hàm giai thừa n ! Định nghĩa n! n! =1 nếu n=0 = n(n-1)! nếu n>0 double f(n :int) ; { If n=0 f =1 else F =n*f(n-1) } 3. Thiết kế... Ví dụ 2 : Bài toán cổ về việc sinh sản của các cặp thỏ. Bài toán được đặt ra như sau: Các con thỏ không bao giờ chết. Hai tháng sau khi ra đời một cặp thỏ mới sẽ sinh ra một cặp thỏ con. Khi đã sinh con rồi thì cứ mỗi tháng tiếp theo chúng lại sinh được một cặp con mới. Giả sử bắt đầu từ một cặp thỏ mới ra đời thì đến tháng thứ n sẽ có bao nhiêu cặp Dãy Fibonacci fib(n) =fib(n-2)+fib(n-1) nếu n>2 =1; nếu n khử đệ qui. Tuy nhiên, đệ qui vẫn có vai trò xứng đáng: nghĩ ra lời giải đệ qui dễ hơn nhiều so với lời giải lặp, và có những lời giải đệ qui có hiệu lực cao (thuật toán sắp xếp nhanh QuickSort). xét định nghĩa: công cụ đệ quy đã cho phép xác định một tập vô hạn các đối tượng bằng một phát biểu hữu hạn. -> 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ữ, định nghĩa một số cấu trúc dữ liệu v.v... 5. Cấu trúc chung của một thủ tục đệ quy Một thủ tục đệ qui gồm có hai phần chính Phần cố định (neo): gía trị khởi đầu cho hàm, thủ tục đệ qui. Phần hạ bậc (phần đệ qui): Tác động của hàm đệ qui được thực hiện thông qua tác động hay giá trị đã được định nghĩa trước. Phân tích giải thuật đệ qui tính giai thừa: f(3)->f(2)->f(1)->f(0)->1 -> như vậy để tính 3! Hàm f được gọi 4 lần. Phân tích Fibonacci: 5. Cấu trúc chung… 6. Tính đúng đắn của các giải thuật đệ quy Để chứng minh tính đúng đắn của một giải thuật đệ qui người ta sử dụng phương pháp qui nạp toán học. Vd: Chứng minh giải thuật đệ qui tính giai thừa F(n). Định nghĩa: F(0)=1 F(n)=n(n-1)(n-2)…2*1;(n>0) Giải thuật Double f(n: int); { If n=0 then f =1 else F=n*f(n-1) } CM: Nếu n=0; theo giải thuật f=1 (như vậy giải thuật đúng khi n=0) Giả sử giải thuật đúng với n=k, nghĩa là F(k)=k*(k-1)*…2*1. Ta phải chứng minh giải thuật đúng với n=k+1; Ta thấy với n=k+1 thì F=n*f(n-1) sẽ được thực hiện. Thay n=k+1 ta được F(k+1)=(k+1)F(k)=(k+1)*k*(k-1)*…2*1.(dpcm) Ví dụ Bài toán “Tháp Hà Nội”. Có n đĩa, kích thước nhỏ dần, mỗi đĩa có lỗ ở giữa. Có thể xếp chồng chúng lên nhau xuyên qua một cọc, đĩa to ở dưới, đĩa nhỏ ở trên để cuối cùng có một chồng đĩa dạng như hình tháp như hình dưới đây. Yêu cầu đặt ra là: Chuyển chồng đĩa từ cọc A sang cọc khác, chẳng hạn cọc C, theo những điều kiện: Mỗi lần chỉ được chuyển một đĩa. Không khi nào có tình huống đĩa to ở trên đĩa nhỏ (dù là tạm thời). Được phép sử dụng một cọc trung gian, chẳng hạn cọc B để đặt tạm đĩa (gọi là cọc trung gian). *) Trường hợp có 1 đĩa: - Chuyển đĩa từ cọc A sang cọc C. *) Trường hợp 2 đĩa: - Chuyển đĩa thứ nhất từ cọc A sang cọc B. - Chuyển đĩa thứ hai từ cọc A sang cọc C. - Chuyển đĩa thứ nhất từ cọc B sang cọc C. Ta thấy với trường hợp n đĩa (n>2) nếu coi n-1 đĩa ở trên, đóng vai trò như đĩa thứ nhất thì có thể xử lý giống như trường hợp 2 đĩa được, nghĩa là: - Chuyển n-1 đĩa trên từ A sang B. - Chuyển đĩa thứ n từ A sang C.ABCABCABCABCBước 1Bước 2Bước 3 - Chuyển n-1 đĩa từ B sang C. Void Chuyen(n, A, B, C) { if n=1 chuyển đĩa từ A sang C; else { call Chuyen(n-1, a, C, B); call Chuyen(1, A, B, C); call Chuyen(n-1, B, A, C) ; } }