Cấu trúc dữ liệu và giải thuật - Chương 4: Tìm kiếm (searching)

pdf 33 trang vanle 4380
Bạn đang xem 20 trang mẫu của tài liệu "Cấu trúc dữ liệu và giải thuật - Chương 4: Tìm kiếm (searching)", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfcau_truc_du_lieu_va_giai_thuat_chuong_4_tim_kiem_searching.pdf

Nội dung text: Cấu trúc dữ liệu và giải thuật - Chương 4: Tìm kiếm (searching)

  1. Chương 4: TÌM KIẾM (SEARCHING)
  2. Nội dung 2 1. Khái quát về tìm kiếm 2. Tìm tuyến tính (Linear Search) 3. Tìm nhị phân (Binary Search) Chương 3: Tìm kiếm
  3. Khái quát về tìm kiếm 3  Tìm kiếm là một yêu cầu rất thường xuyên trong đời sống hàng ngày cũng như trong tin học  Ví dụ:  Tìm kiếm một sinh viên trong lớp  Tìm kiếm một tập tin, thư mục trong máy  Để đơn giản ta xét bài toán tìm kiếm như sau:  Cho một dãy số gồm các phần tử a1, a2, , an. Cho biết trong dãy này có phần tử nào có giá trị bằng X (cho trước) hay không? Chương 33:: Tìm kiếm
  4. Khái quát về tìm kiếm 4  Xét hai cách tìm kiếm:  Tìm kiếm tuyến tính (Linear Search) hay còn gọi là tìm kiếm tuần tự (Sequential Search)  Tìm kiếm nhị phân (Binary Search) Chương 3: Tìm kiếm
  5. Nội dung 5 1. Khái quát về tìm kiếm 2. Tìm tuyến tính (Linear Search) 3. Tìm nhị phân (Binary Search) Chương 3: Tìm kiếm
  6. 2. Tìm tuyến tính (Linear Seach) 6 Ý tưởng:  Bắt đầu từ phần tử đầu tiên của danh sách, so sánh lần lượt từng phần tử của danh sách với giá trị X cần tìm  Nếu có phần tử bằng X, thuật toán dừng lại (thành công)  Nếu đến cuối danh sách mà không có phần tử nào bằng X, thuật toán dừng lại (không thành công)  If we find a match, the search terminates successfully by returning the index of the element  If the end of the list is encountered without a match, the search terminates unsuccessfully Chương 3: Tìm kiếm
  7. 2. Tìm tuyến tính (Linear Seach) 7 Thuật toán: B1: i = 0 ; // bắt đầu từ phần tử đầu tiên B2: so sánh A[i] với X, có 2 khả năng :  A[i] = X : Tìm thấy. Dừng  A[i] ≠ X : Sang B3 B3: i=i+1 // Xét phần tử tiếp theo trong mảng Nếu i=n : Hết mảng, không tìm thấy. Dừng Ngược lại: lặp lại B2 Chương 3: Tìm kiếm
  8. 2. Tìm tuyến tính (Linear Seach) 8 Ví dụ: 12 2 8 5 1 X=8 X=8 i=0 12 2 8 5 1 X=8 i=1 12 2 8 5 1 X=8 i=2 12 2 8 5 1 Dừng Chương 3: Tìm kiếm
  9. 2. Tìm tuyến tính (Linear Seach) 9 5 Vị trí = 2 Khóa tìm 0 1 2 3 4 5 6 7 7 13 5 21 6 2 8 15 Tìm thành công Số lần so sánh: 3 Chương 3: Tìm kiếm
  10. 2. Tìm tuyến tính (Linear Seach) 10 9 Khóa tìm 0 1 2 3 4 5 6 7 7 13 5 21 6 2 8 15 Không tìm thấy Số lần so sánh: 8 Chương 3: Tìm kiếm
  11. 2. Tìm tuyến tính (Linear Seach) 11 void lsearch (int list[], int n, int key) { int flag = 0; // giả sử lúc đầu chưa tìm thấy for(int i=0; i<n; i++) if (list[i] == key) { cout<<“found at position”<<i; flag =1; // tìm thấy break; } if (flag == 0) cout<<“not found”; } Chương 3: Tìm kiếm
  12. 2. Tìm tuyến tính (Linear Seach) 12 int lsearch(int list[], int n, int key) { int find= -1; for(int i=0; i<n; i++) if (list[i] == key) { find = i; break; } return find; } Chương 3: Tìm kiếm
  13. 13  Phân tích, đánh giá thuật toán Trường hợp Số lần so sánh Giải thích Tốt nhất 1 Phần tử đầu tiên có giá trị x Xấu nhất n+1 Phần tử cuối cùng có giá trị x Trung bình (n+1)/2 Giả sử xác suất các phần tử trong mảng nhận giá trị x là như nhau.  Vậy giải thuật tìm tuyến tính có độ phức tạp tính toán cấp n: T(n) = O(n) Chương 3: Tìm kiếm
  14. Tìm tuyến tính (Linear Seach) 14 Phân tích, đánh giá thuật toán: Trường hợp Số lần so sánh Giải thích Tốt nhất 1 Phần tử đầu tiên có giá trị x Xấu nhất n+1 Phần tử cuối cùng có giá trị x Trung bình (n+1)/2 Giả sử xác suất các phần tử trong mảng nhận giá trị x là như nhau. Chương 3: Tìm kiếm
  15. Nội dung 15 1. Khái quát về tìm kiếm 2. Tìm tuyến tính (Linear Search) 3. Tìm nhị phân (Binary Search) Chương 3: Tìm kiếm
  16. 3. Tìm nhị phân (Binary Seach) 16  Điều kiện:  Danh sách phải được sắp xếp trước  Ý tưởng:  So sánh giá trị muốn tìm X với phần tử nằm ở vị trí giữa của danh sách:  Nếu bằng, tìm kiếm dừng lại (thành công)  Nếu X lớn hơn thì tiếp tục tìm kiếm ở phần danh sách bên phải phần tử giữa  Nếu X nhỏ hơn thì tiếp tục tìm kiếm ở phần danh sách bên trái phần tử giữa  We compare the element with the element placed approximately in the middle of the list  If a match is found, the search terminates successfully  Otherwise, we continue the search for the key in a similar manner either in the upper half or the lower half Chương 3: Tìm kiếm
  17. 3. Tìm nhị phân (Binary Seach) 17 Thuật toán: B1: Left = 0, Right = n-1 B2: Mid = (Left + Right)/2 // lấy vị trí cận giữa B3: So sánh X với A[Mid], có 3 khả năng xảy ra:  A[Mid] = X // tìm thấy. Dừng thuật toán  A[Mid] > X Right = Mid-1 // Tiếp tục tìm trong dãy A[0] A[Mid-1]  A[Mid] < X Left = Mid+1 // Tiếp tục tìm trong dãy A[Mid+1] A[Right] B4: Nếu (Left <= Right) // Còn phần tử chưa xét Lặp lại B2 Ngược lại: Kết thúc Chương 3: Tìm kiếm
  18. 3. Tìm nhị phân (Binary Seach) 18 10 Vi trí = 3 Khóa tìm Khóa cần tìm nhỏlớnbằng hơnhơn hoặc bằng 0 1 2 3 4 5 6 7 8 9 2 5 8 10 12 13 15 18 21 24 left mid right Tìm thấy Số lần so sánh: 4 Chương 3: Tìm kiếm
  19. 3. Tìm nhị phân (Binary Seach) 19 0 1 2 3 4 5 6 7 Ví dụ: 1 2 4 5 6 8 12 15 X=8 Left=0, Right=7, Mid=3 X=8 1 2 4 5 6 8 12 15 Left=4, Right=7, Mid=5 X=8 1 2 4 5 6 8 12 15 Dừng Chương 3: Tìm kiếm
  20. 3. Tìm nhị phân (Binary Seach) 20 void BSearch (int list[], int n, int key) Không đệ quy { int left, right, mid, flag = 0; left = 0; right = n-1; while (left <= right) { mid = (left + right)/2; if( list[mid] == key) { cout<<"found:"<< mid; flag =1; // đánh dấu tìm thấy break; } else if (list[mid] < key) left = mid +1; else right = mid -1; } if (flag == 0) cout<<"not found"; } Chương 3: Tìm kiếm
  21. 3. Tìm nhị phân (Binary Seach) 21 int BSearch_Recursion (int list[], int key, int left, int right) Đệ quy { if (left <= right) { int mid = (left + right)/2; if (key == list[mid]) return mid; // trả về vị trí tìm thấy key else if (key < list[mid]) return BSearch_Recursion (list, key, left, mid-1); else return BSearch_Recursion (list, key, mid+1, right); } return -1; // không tìm thấy } Chương 3: Tìm kiếm
  22. 3. Tìm nhị phân (Binary Seach) 22  Phân tích, đánh giá thuật toán: Trường hợp Số lần so sánh Giải thích Tốt nhất 1 Phần tử giữa của mảng có giá trị x Xấu nhất log 2 n Không có x trong mảng Giả sử xác suất các phần tử trong mảng Trung bình log (n/2) 2 nhận giá trị x là như nhau  Vậy giải thuật tìm nhị phân có độ phức tạp tính toán cấp n: T(n) = O(log2n) Chương 3: Tìm kiếm
  23. Nhận xét 23  Tìm Tuyến Tính không phụ thuộc vào thứ tự của các phần tử, do vậy đây là phương pháp tổng quát nhất để tìm kiếm trên một dãy bất kỳ  Tìm Nhị Phân dựa vào quan hệ giá trị của các phần tử mảng để định hướng trong quá trình tìm kiếm, do vậy chỉ áp dụng được cho những dãy đã có thứ tự  Giải thuật Tìm Nhị Phân tiết kiệm thời gian hơn rất nhiều so với giải thuật Tìm Tuyến Tính do: Tnhị phân(n) = O(log2n) < Ttuyến tính (n) = O(n) Chương 3: Tìm kiếm
  24. Nhận xét 24  Tuy nhiên khi muốn áp dụng giải thuật tìm Nhị Phân cần phải xét đến thời gian sắp xếp dãy số để thỏa điều kiện dãy số có thứ tự  Thời gian này không nhỏ, và khi dãy số biến động cần phải tiến hành sắp xếp lại  Tất cả các nhu cầu đó tạo ra khuyết điểm chính cho giải thuật tìm Nhị Phân  Ta cần cân nhắc nhu cầu thực tế để chọn một trong hai giải thuật tìm kiếm trên sao cho có lợi nhất Chương 3: Tìm kiếm
  25. Tìm tuyến tính (Linear Seach) 25 Cài đặt thuật toán: int LinearSearch (int A[], int n, int X) { int i = 0; while (A[i] != X && i <n) // phần tử mảng M tính từ 0 i++; if (i < n) return (i); // trả về vị trí tìm thấy X return (-1); } Chương 3: Tìm kiếm
  26. Tìm tuyến tính (Linear Seach) 26 Cải tiến thuật toán:  Mỗi bước lặp với thuật toán trên cần thực hiện 2 phép so sánh ý tưởng giảm bớt phép so sánh bằng cách thêm vào mảng một phần tử cầm canh (sentinel/stand by) có giá trị bằng X để nhận diện ra sự hết mảng khi duyệt. B1: i = 1 B2: A[n] = X B3: Nếu A[i] X Thì i++ Ngược lại: Lặp lại B3 B4: Nếu i < n Thì Tìm thấy phần tử có giá trị X ở vị trí i B5: Nguợc lại: Thì không tìm thấy phần tử có giá trị X B6: Kết thúc Chương 3: Tìm kiếm
  27. Tìm tuyến tính (Linear Seach) Cài đặt thuật toán cải tiến: 27 int LinearSearchCaiTien (int A[], int n, int X) { int i = 0; A[n] = X; // phần tử mảng A tính từ 0 while (A[i] != X) i++; if (i < n) return (i); return (-1); } Chương 3: Tìm kiếm
  28. Tìm tuyến tính (Linear Seach) 28 Phân tích, đánh giá thuật toán cải tiến:  Trường hợp tốt nhất (phần tử đầu tiên của mảng có giá trị = X)  Số phép gán Gmin = 2  Số phép so sánh Smin = 2  Trường hợp xấu nhất (không có phần tử nào của mảng có giá trị = X)  Số phép gán Gmax = 2  Số phép so sánh Smax = (N + 1) + 1=N+2  Trung bình  Số phép gán Gavg = (2+2)/2=2  Số phép so sánh Savg = ((N + 2)+2)/2=N/2+2 Chương 3: Tìm kiếm
  29. Tìm tuyến tính (Linear Seach) 29 Ví dụ: Tìm tuyến tính Chương 3: Tìm kiếm
  30. Tìm nhị phân (Binary Seach) 30 Thuật toán không đệ quy (Non-Recursion Algorithm) B1: First = 1 B2: Last = n B3: Nếu (First > Last) // hết phạm vi tìm kiếm Không tìm thấy, Thực hiện B8 B4: Mid = (First + Last )/2 B5: Nếu (X = A[Mid]) Tìm thấy tại vị trí Mid Ngược lại: Thực hiện B6 B6: Nếu (X A[Mid]) First = Mid + 1 và lặp lại B3 B8: Kết thúc Chương 3: Tìm kiếm
  31. Tìm nhị phân (Binary Seach) 31 Cài đặt Thuật toán không đệ quy (Non-Recursion Algorithm) int NRBinarySearch (T M[], int N, T X) { int First = 0; int Last = N-1; while (First <= Last) { int Mid = (First + Last)/2; if (X == M[Mid]) return Mid; if (X < M[Mid]) Last = Mid –1 ; else First = Mid + 1; } return (-1); } Chương 3: Tìm kiếm
  32. 3. Tìm nhị phân (Binary Seach) 32 Phân tích, đánh giá thuật toán không đệ quy:  Trường hợp tốt nhất (phần tử đầu tiên của mảng có giá trị = X)  Số phép gán Gmin = 3  Số phép so sánh Smin = 2  Trường hợp xấu nhất (không có phần tử nào của mảng có giá trị = X)  Số phép gán Gmax = 2log2N +4  Số phép so sánh Smax =3log2N +1  Trung bình  Số phép gán Gavg = log2N +3.5  Số phép so sánh Savg = ½(3log2N + 3) Chương 3: Tìm kiếm
  33. 3. Tìm nhị phân (Binary Seach) 33 Phân tích, đánh giá thuật toán đệ quy:  Trường hợp tốt nhất (phần tử đầu tiên của mảng có giá trị = X)  Số phép gán Gmin = 1  Số phép so sánh Smin = 2  Trường hợp xấu nhất (không có phần tử nào của mảng có giá trị = X)  Số phép gán Gmax = log2N +1  Số phép so sánh Smax =3log2N +1  Trung bình  Số phép gán Gavg = 1/2log2N +1  Số phép so sánh Savg = ½(3log2N + 3) Chương 3: Tìm kiếm