Bài 2: Kỹ thuật tìm kiếm (searching)

− Thuật toán tiến hành so sánh x lần lượt với phần tử thứ nhất, thứ hai, . của mảng a cho đến khi gặp được phần tử có khóa cần tìm, hoặc đã tìm hết mảng mà không thấy x. − Các bước tiến hành nhưsau : Bước 1: i = 1; // bắt đầu từ phần tử đầu tiên của dãy Bước 2: 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 Bước 3. Bước 3 : i = i+1; // xét tiếp phần tử kế 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 Bước 2

pdf25 trang | Chia sẻ: lylyngoc | Lượt xem: 1861 | Lượt tải: 2download
Bạn đang xem trước 20 trang tài liệu Bài 2: Kỹ thuật tìm kiếm (searching), để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
1Bài 2: Kỹ Thuật Tìm Kiếm (Searching) GV: Nguyễn Hữu Thể Khoa CNTT – Đại Học Cửu Long CTDL1- Nguyễn Hữu Thể 2 NỘI DUNG 1. Tìm kiếm tuyến tính1 2. Tìm kiếm nhị phân2 5 CTDL1- Nguyễn Hữu Thể 3 1. Tìm kiếm tuyến tính (sequential search)  Giải thuật − Thuật toán tiến hành so sánh x lần lượt với phần tử thứ nhất, thứ hai, ... của mảng a cho đến khi gặp được phần tử có khóa cần tìm, hoặc đã tìm hết mảng mà không thấy x. − Các bước tiến hành như sau : Bước 1: i = 1; // bắt đầu từ phần tử đầu tiên của dãy Bước 2: 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 Bước 3. Bước 3 : i = i+1; // xét tiếp phần tử kế 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 Bước 2. CTDL1- Nguyễn Hữu Thể 4 1. Tìm kiếm tuyến tính (sequential search) int LinearSearch(int a[], int n, int x) { int i=0; while(i<n && a[i]!=x) i++; if (i<n) return i; // a[i] là phần tử có khoá x else return -1; // tìm hết mảng nhưng không có x } CTDL1- Nguyễn Hữu Thể 5 1. Tìm kiếm tuyến tính (sequential search) int LinearSearch(int a[], int n, int x) { for(int i=0;i<n; i++) { if (a[i]==x) return i; // a[i] là phần tử có khoá x } return -1; // tìm hết mảng nhưng không có x } CTDL1- Nguyễn Hữu Thể 6 1. Tìm kiếm tuyến tính (sequential search) − Ví dụ: Cho dãy số a 12 2 8 5 1 6 4 15 − Giá trị cần tìm: 8 i=0 i=1 i=2 CTDL1- Nguyễn Hữu Thể 7 1. Tìm kiếm tuyến tính (sequential search) 5 Khóa tìm 7 13 5 21 6 2 8 15 0 1 2 3 4 5 6 7 Vị trí = 2 Tìm thành công Số lần so sánh: 3 CTDL1- Nguyễn Hữu Thể 8 1. Tìm kiếm tuyến tính (sequential search) 9 7 13 5 21 6 2 8 15 0 1 2 3 4 5 6 7 Không tìm thấy Số lần so sánh: 8 Khóa tìm CTDL1- Nguyễn Hữu Thể 9 1. Tìm kiếm tuyến tính (sequential search) − Cải tiến cài đặt: dùng phương pháp “lính canh”  Đặt thêm một phần tử có giá trị x vào cuối mảng  Bảo đảm luôn tìm thấy x trong mảng  Sau đó dựa vào vị trí tìm thấy để kết luận. CTDL1- Nguyễn Hữu Thể 10 1. Tìm kiếm tuyến tính – pp “lính canh” int LinearSearch(int a[], int n, int x) { int i=0; // mảng gồm N phần tử từ a[0]..a[N-1] a[n] = x; // thêm lính canh vào cuối dãy (ptử thứ n+1) while(a[i]!=x) i++; if (i<n) return i; // a[i] là phần tử có khoá x else return -1; // tìm hết mảng nhưng không có x } CTDL1- Nguyễn Hữu Thể 11 1. Tìm kiếm tuyến tính (sequential search) − Đánh giá giải thuật: − Vậy giải thuật tìm tuần tự có độ phức tạp tính toán cấp n: T(n) = O(n) CTDL1- Nguyễn Hữu Thể 12 1. Tìm kiếm tuyến tính (sequential search) Nhận xét:  Giải thuật tìm tuyến tính không phụ thuộc vào thứ tự của các phần tử trong danh sách. CTDL1- Nguyễn Hữu Thể 13 2. Tìm kiếm nhị phân − Đối với những dãy đã có thứ tự (giả sử thứ tự tăng ), các phần tử trong dãy có quan hệ a[i-1] ≤ a[i] ≤ a[i+1] − Nếu x > a[i] thì x chỉ có thể xuất hiện trong đoạn [a[i+1] ,a[N]] của dãy − Nếu x < a[i] thì x chỉ có thể xuất hiện trong đoạn [a[0] ,a[i-1]] của dãy . CTDL1- Nguyễn Hữu Thể 14 2. Tìm kiếm nhị phân − Ý tưởng:  Tại mỗi bước tiến hành so sánh x với phần tử nằm ở vị trí giữa của dãy tìm kiếm hiện hành.  Dựa vào kết quả so sánh này để quyết định giới hạn dãy tìm kiếm ở bước kế tiếp là nửa trên hay nửa dưới của dãy tìm kiếm hiện hành CTDL1- Nguyễn Hữu Thể 15 2. Tìm kiếm nhị phân Bước 1: left = 1; right = N; Bước 2: mid = (left+right)/2; So sánh a[mid] với x, có 3 khả năng : • a[mid] = x: Tìm thấy. Dừng • a[mid] > x: //tìm tiếp x trong dãy con aleft .. amid -1 : right =mid - 1; • a[mid] < x: //tìm tiếp x trong dãy con amid +1 .. aright : left = mid + 1; Bước 3: Nếu left ≤ right //còn phần tử chưa xét Lặp lại Bước 2. Ngược lại: Dừng; //Ðã xét hết tất cả các phần tử. CTDL1- Nguyễn Hữu Thể 16 2. Tìm kiếm nhị phân int BinarySearch(int a[],int n,int x ) { int left =0, right = n-1, mid; while (left <= right) { mid = (left + right)/2; if (x == a[mid]) return mid;//Tìm thấy x tại mid if (x < a[mid]) right = mid -1; else left = mid +1; } return -1; // trong dãy không có x } CTDL1- Nguyễn Hữu Thể 17 2. Tìm kiếm nhị phân 10 Khóa tìm 2 58 10 12 13 15 18 21 24 0 1 2 3 4 5 6 7 8 9 left rightmid CTDL1- Nguyễn Hữu Thể 18 2. Tìm kiếm nhị phân 10 Khóa tìm 2 58 10 12 13 15 18 21 24 0 1 2 3 4 5 6 7 8 9 left rightmid CTDL1- Nguyễn Hữu Thể 19 2. Tìm kiếm nhị phân 10 Khóa tìm 2 58 10 12 13 15 18 21 24 0 1 2 3 4 5 6 7 8 9 left right mid CTDL1- Nguyễn Hữu Thể 20 2. Tìm kiếm nhị phân 10 Khóa tìm 2 58 10 12 13 15 18 21 24 0 1 2 3 4 5 6 7 8 9 left right mid CTDL1- Nguyễn Hữu Thể 21 2. Tìm kiếm nhị phân 10 Khóa tìm 2 58 10 12 13 15 18 21 24 0 1 2 3 4 5 6 7 8 9 Vi trí = 3 Tìm thấy Số lần so sánh: 4 CTDL1- Nguyễn Hữu Thể 22 2. Tìm kiếm nhị phân int BinarySearch(int a[],int N,int x ) { int left =0, right = N-1; int mid; do{ mid = (left + right)/2; if (x = a[mid]) return mid; //Thấy x tại mid else if (x < a[mid]) right = mid -1; else left = mid +1; }while (left <= right); return -1; // Tìm hết dãy mà không có x } CTDL1- Nguyễn Hữu Thể 23 2. Tìm kiếm nhị phân − Đánh giá giải thuật: − Giải thuật tìm nhị phân có độ phức tạp tính toán cấp logn: T(n) = O(log 2 n) CTDL1- Nguyễn Hữu Thể 24 2. Tìm kiếm nhị phân Nhận xét:  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  => 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 tuần tự do Tnhị phân (n) = O(log 2 n) < Ttuần tự (n) = O(n). 25
Tài liệu liên quan