Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
3,1 MB
Nội dung
DATA STRUCTURE AND ALGORITHM Recursion CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT Đệ qui Dr Dao Nam Anh Data Structure and Algorithm Resource - Reference Slides adapted from Robert Sedgewick, and Kevin Wayne, edit by Dao Nam Anh Major Reference: • Robert Sedgewick, and Kevin Wayne, “Algorithms” Princeton University, 2011, Addison Wesley • Algorithm in C (Parts 1-5 Bundle)- Third Edition by Robert Sedgewick, Addison-Wesley • Cấu trúc liệu giải thuật, Đinh Mạnh Tường • Giải thuật lập trình, Lê Minh Hồng, Đại Học Sư Phạm, 2002 Data Structure and Algorithm Khái niệm • Là phương pháp lập trình cho phép hàm gọi lại trực tiếp gián tiếp Ví dụ: void Test() { Test(); } Reproductive Parts M C Escher, 1948 • Một chương trình đệ quy định nghĩa đệ quy khơng thể gọi đến mãi mà phải có điểm dừng đến trường hợp đặc biệt đó, mà ta gọi trường hợp suy biến (degenerate case) Data Structure and Algorithm Khái niệm Phương pháp thiết kế giải thuật đệ quy: • • Tham số hố tốn • Tìm trường hợp suy biến Phân tích trường hợp chung : đưa toán dạng toán loại có phạm vi giải nhỏ theo nghiã tiến đến trường hợp suy biến Data Structure and Algorithm Khái niệm Chương trình đệ quy gồm hai phần chính: Phần sở: Điều kiện thoát khỏi đệ quy (điểm dừng) Phần đệ quy: Trong phần thân chương trình có lời gọi đến thân chương trình với giá trị tham số nhỏ giá trị ban đầu Data Structure and Algorithm Greatest Common Divisor Ước số chung nhỏ • Gcd Tìm số ngun lớn nhất, chia hết bới hai số p q • Ví dụ gcd(4032, 1272) = 24 4032 = 26 32 71 1272 = 23 31 531 gcd = 23 31 = 24 Data Structure and Algorithm Greatest Common Divisor Ước số chung nhỏ • Gcd Tìm số nguyên lớn nhất, chia hết bới hai số p q p if q gcd( p, q) gcd(q, p % q) otherwise • base case reduction step, converges to base case Euclid's algorithm [Euclid 300 BCE] gcd(4032, 1272)= = = = = gcd(1272, 216) gcd(216, 192) gcd(192, 24) gcd(24, 0) 24 4032 = 1272 + 216 Data Structure and Algorithm Greatest Common Divisor Ước số chung nhỏ base case p if q gcd( p, q) gcd(q, p % q) otherwise reduction step, converges to base case p q q x x x x x p = 8x q = 3x gcd(p, q) = x p % q x x x gcd Data Structure and Algorithm Greatest Common Divisor Ước số chung nhỏ p if q gcd( p, q) gcd(q, p % q) otherwise public static int gcd(int p, int q) { if (q == 0) return p; else return gcd(q, p % q); } base case reduction step, converges to base case base case reduction step Data Structure and Algorithm Tính giai thừa đệ qui Data Structure and Algorithm 10 Tháp Hà nội:n, Giải pháp đệ qui left 3, true 14 28 15 2, false 13 1, true 16 21 1, true left 2, false 10 right 1, true 1, true 17 18 11 12 left 22 27 left 19 20 left 23 right Data Structure and Algorithm 24 25 26 left 36 Tháp Hà nội:n, Giải pháp đệ qui left 3, true 14 2, false 13 1, true 1, true left 2, false 10 right 11 12 left left left right Data Structure and Algorithm left 37 Tháp Hà nội:n, Giải pháp đệ qui left 3, true 14 28 15 2, false 13 1, true 16 21 1, true left 2, false 10 right 1, true 1, true 17 18 11 12 left 22 27 left 19 20 left 23 right Data Structure and Algorithm 24 25 26 left 38 Tháp Hà nội: Giải pháp đệ qui • Remarkable properties of recursive solution Takes 2n - moves to solve n disc problem Sequence of discs is same as subdivisions of ruler Every other move involves smallest disc • Recursive algorithm may reveal fate of world Takes 585 billion years for n = 64 (at rate of disc per second) Reassuring fact: any solution takes at least this long! Data Structure and Algorithm 39 Divide-and-Conquer Chia để trị • Chia để trị Chia thành nhiều vấn đề nhỏ với cấu trúc Giải vấn đề nhỏ đệ qui giải pháp Nhóm kết để có giải pháp cho tốn Divide et impera Veni, vidi, vici • - Julius Caesar Ứng dụng thực tế Xử lý liệu: FFT for signal processing Chương trình dịch: Parsers for programming languages Tính vi phân: Multigrid methods for solving PDEs Sắp xếp: Quicksort and mergesort for sorting Chía nhỏ vấn đề: Hilbert curve for domain decomposition Data Structure and Algorithm 40 Fibonacci Numbers Dãy số Fibonacci Dãy số Fibonacci bắt nguồn từ toán cổ việc sinh sản cặp thỏ Bài toán đặt sau: • • Các thỏ khơng chết • Khi sinh tháng chúng lại sinh cặp Hai tháng sau đời, cặp thỏ sinh cặp thỏ (một đực, cái) Data Structure and Algorithm 41 Fibonacci Numbers Dãy số Fibonacci • Giả sử từ đầu tháng có cặp đời đến tháng thứ n có cặp • Ví dụ, n = 5, ta thấy: Giữa tháng thứ 1: cặp (ab) (cặp ban đầu) Giữa tháng thứ 2: cặp (ab) (cặp ban đầu chưa đẻ) Giữa tháng thứ 3: cặp (AB)(cd) (cặp ban đầu đẻ thêm cặp con) Giữa tháng thứ 4: cặp (AB)(cd)(ef) (cặp ban đầu tiếp tục đẻ) Giữa tháng thứ 5: cặp (AB)(CD)(ef)(gh)(ik) (cả cặp (AB) (CD) đẻ) Data Structure and Algorithm 42 Fibonacci Numbers Dãy số Fibonacci • Bây giờ, ta xét tới việc tính số cặp thỏ tháng thứ n: F(n) • Nếu cặp thỏ tháng thứ n - sinh cặp thỏ số cặp thỏ tháng thứ n là: F(n) = * F(n - 1) Data Structure and Algorithm 43 Fibonacci Numbers and Nature pinecone cauliflower Data Structure and Algorithm 44 Fibonacci Numbers • if n F(n) 1 if n F(n 1) F(n 2) otherwise Fibonacci numbers 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, … Fibonacci rabbits L P Fibonacci (1170 - 1250) Data Structure and Algorithm 45 Fibonacci Numbers • if n F(n) 1 if n F(n 1) F(n 2) otherwise Fibonacci numbers 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, … public static long F(int n) { if (n == 0) return 0; if (n == 1) return 1; return F(n-1) + F(n-2); } Data Structure and Algorithm 46 Đánh giá Đệ qui • Q Cách tính có hiệu không F(50)? public static long F(int n) { if (n == 0) return 0; if (n == 1) return 1; return F(n-1) + F(n-2); } • A Khơng hiệu F(50) is called once F(50) F(49) is called once F(49) F(48) is called times F(48) F(47) is called times F(48) F(47) F(47) F(46) F(46) F(45) F(47) F(46) F(46) F(45) F(45) F(44) F(46) is called times F(45) is called times F(1) is called 12,586,269,025 times recursion tree for naïve Fibonacci function Data Structure and Algorithm F(50) 47 Đánh giá đệ qui • Q Cách sau cho F(50) có hiệu khơng? public static long(int n) { long[] F = new long[n+1]; F[0] = 0; F[1] = 1; for (int i = 2; i