Chương 2.1. Giải thuật tìm kiếm
ầ
Tr n Minh Thái Email: minhthai@itc.edu.vn Website: www.minhthai.edu.vn
1
Mục tiêu
• Xác định được vai trò của tìm kiếm và sắp xếp trong hệ thống
• Nắm vững và minh họa được giải thuật tìm kiếm tuyến tính và
thông tin
• Cài đặt được giải thuật tìm kiếm bằng ngôn ngữ C/C++
2
tìm kiếm nhị phân trên mảng một chiều
Suy nghĩ
?
Tại sao hầu hết phần mềm phải có chức năng tìm kiếm và sắp xếp, mối quan hệ giữa tìm kiếm và sắp xếp?
3
Nhu cầu tìm kiếm và sắp xếp
• Tìm kiếm: Có trong hầu hết trong các hệ thống thông tin
• Muốn tìm kiếm nhanh và hiệu quả dữ liệu có thứ tự sắp
4
xếp
Các giải thuật tìm kiếm
• Có 2 giải thuật thường được áp dụng: Tìm tuyến tính và tìm nhị
• Đặc tả:
phân.
a3 a4
a2
a5
…
aN
a1 • Tập dữ liệu được lưu trữ là dãy số a1, a2, ... ,aN.
an- 1
• Khai báo: int a[N];
• Khóa cần tìm: int x;
5
Tìm kiếm tuyến tính (Linear Search)
Ý tưởng
Lần lượt so sánh x với phần tử thứ nhất, thứ hai, ... của mảng a
6
cho đến khi gặp được phần tử cần tìm, hoặc hết mảng
Tìm kiếm tuyến tính
• Minh họa tìm x =10
10
Đã tìm Chưa hết thấy tại mảng vị trí 5
12 3
7 1
10 10 5
32 6
13 7
9 8
15 9
3 10
41 5 4 2 • Minh họa tìm x =25
25
Đã hết Chưa hết mảng mảng
5 2
12 3
41 4
10 5
32 6
13 7
9 8
15 9
3 10
7 1
7
Giải thuật
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. 8
Nguyên tắc cài đặt hàm tìm kiếm
• Nếu có xuất hiện phần tử có giá trị x thì trả về vị trí tìm được
• Ngược lại thì trả về -1
9
Cài đặt int LinearSearch(int a[], int N, int x)
{
int i=0;
while ((i i++; if(i==N) return -1; //tìm hết mảng else return i; //a[i] là phần tử có khoá x 10 } • Minh họa tìm x =10 Dùng lính canh giúp giảm bớt phép so sánh 12
3 7
1 32
6 13
7 15
9 3
10 9
8 11 41
5
4
2
• Minh họa tìm x = 25 5
2 12
3 41
4 10
5 32
6 13
7 3
10 15
9 7
1 9
8 11 int i=0; a[N] = x; // thêm phần tử x sau mảng
while (a[i]!=x )
i++; return -1; // tìm hết mảng if (i==N)
else return i; // tìm thấy x tại vị trí i }
Độ phức tạp tính toán cấp n: T(n)=O(n) 12 Cài đặt
int LinearSearch2(int a[],int N,int x)
{ 13 • Áp dụng đối với dãy số đã có thứ tự • Mỗi bước tiến hành so sánh x với phần tử ở giữa của dãy hiện Ý tưởng 14 hành để quyết định phạm vi tìm kế tiếp Minh họa tìm x = 41 14
14
14
14 16
16
16
16 19
19
19
19 41
41
41
41 46
46
46
46 63
63
63
63 3
3
3
3 22
22
22
22 51
51
51
51 71
71
71
71 2
2
2
2 3
3
3
3 4
4
4
4 6
6
6
6 7
7
7
7 9
9
9
9 1
1
1
1 5
5
5
5 8
8
8
8 10
10
10
10 15 Minh họa tìm x = 45 14
14
14
14
14 16
16
16
16
16 19
19
19
19
19 41
41
41
41
41 46
46
46
46
46 63
63
63
63
63 3
3
3
3
3 22
22
22
22
22 51
51
51
51
51 71
71
71
71
71 2
2
2
2
2 3
3
3
3
3 4
4
4
4
4 6
6
6
6
6 7
7
7
7
7 9
9
9
9
9 1
1
1
1
1 5
5
5
5
5 8
8
8
8
8 10
10
10
10
10 16 //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 tìm tiếp. 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ử. 17 Giải thuật
Bước 1: left = 1; right = N; //tìm kiếm tất cả các phần tử
Bước 2:
mid = (left+right)/2; // lấy mốc so sánh
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: int BinarySearch(int a[],int N,int x )
{ int left =0; right = N-1; int mid;
while (left <= right)
{ mid = (left + right)/2; if (x == a[mid]) return mid;//Thấy x tại mid if (x < a[mid]) right = mid -1; else
left = mid +1; }
return -1; // Tìm hết dãy mà không có x 18 }
Độ phức tạp tính toán cấp n: T(n)=O(log 2n) 19 #include #include #include #define MAX 1000 void TaoMang(int a[], int N); void XuatMang(int a[], int N); 20 int LinearSearch(int a[], int N, int x); void main() { srand((usigned int) time (NULL)); int a[MAX], N = 20, x, kq; TaoMang(a, N); XuatMang(a, N); cout<<“Nhap gia tri can tim: “; cin>>x; kq=LinearSearch(a, N, x); if(kq==-1) cout<<“Khong co phan tu can tim”; else cout<<“Phan tu can tim tai vi tri: ”< 21 } void TaoMang(int a[], int N) { for(int i=0; i a[i]=rand()%N; } void XuatMang(int a[], int N) { for(int i=0; i cout<
22 } int LinearSearch(int a[], int N, int x) { int i=0; while ((i i++; if(i==N) return -1; else return i; } 23 Viết chương trình tự động phát sinh ra mảng có giá trị ngẫu nhiên có thứ tự tăng dần; nhập vào giá trị cần tìm x; in ra vị trí xuất hiện của x (nếu có) và số lần so sánh với mỗi phương pháp tìm kiếm: 24 tuyến tính và nhị phân • LT1_1: Cho dãy số sau: 3
1 4
2 6
3 6
4 12
5 16
6 21
7 34
8 41
9 80
10 • LT1_2: Xây dựng giải thuật tìm kiếm phần tử có giá trị nhỏ nhất Cho biết vị trí tìm thấy và số lần so sánh để tìm được phần tử
có giá trị x = 6 khi áp dụng giải thuật tìm kiếm: tuyến tính và nhị
phân. 25 trong dãy số: Dùng mã tự nhiên, mã giả và lưu đồ. • LT1_1: Tìm x = 6 3
1 4
2 6
3 6
4 12
5 16
6 21
7 34
8 41
9 80
10 Tìm x theo phương pháp tuyến tính Vị trí So sánh với Kết quả x i=1
i=2
i=3 (a[i]=3) (cid:0)
x Tăng vị trí i
(a[i]=4) (cid:0)
x Tăng vị trí i
(a[i]=6) = x Dừng, trả về vị trí i (3) 26 • LT1_1: Tìm x = 6 3
1 4
2 6
3 6
4 12
5 16
6 21
7 34
8 41
9 80
10 ả Tìm x theo phương pháp nhị phân
Xét đo nạ K t quế ậ ị
V trí
So sánh
v i xớ
ạ
ữ
gi a đo n
l=1, r=10 m=(l+r)/2=5 (a[m]=12) (cid:0) ậ l=1, r=4 m=(l+r)/2=2 (a[m]=4) (cid:0) ậ
x C p nh t r=m1=4
(a[m]>x xét trái)
ậ
x C p nh t l=m+1=3 ả ề ị l=3, r=4 m=(l+r)/2=3 (a[m] 28 • Input: Mảng số nguyên a, kích thước n • Output: vt: vị trí phần tử có giá trị nhỏ nhất • Mã tự nhiên: Bước 1: i=2, vt=1; Bước 2: Nếu i>N thì trả về giá trị vt, kết thúc; Bước 3: Nếu a[i]
29 i=i+1; Lặp lại Bước 2; • Input: Mảng số nguyên a, kích thước n • Output: vt: vị trí phần tử có giá trị nhỏ nhất • Pseudocode: i=2, vt=1; vt=i; i=i+1; 30 • Flow Chart: 31 32Cải tiến
10
10
10
10
5
25
25
25
11
Q & A
Tìm kiếm nhị phân (Binary Search)
x
x
x
Tìm thấy x tại vị
trí 6
l
m
m
r
m
x
x
x
x
l
m
m
r
l > r: Kết thúc:
Không tìm thấy
m
m
Q & A
Code minh họa
Bài tập áp dụng
Bài tập lý thuyết
Bài tập lý thuyết – Hướng dẫn
Bài tập lý thuyết – Hướng dẫn
Q & A
Bài tập lý thuyết – Hướng dẫn LT1_2
Bài tập lý thuyết – Hướng dẫn LT1_2
WHILE i ≤ N DO
IF a[i]
END WHILE
RETURN vt;
Bài tập lý thuyết – Hướng dẫn LT1_2
Q & A