Chương 2.1. Giải thuật
tìm kiếm
Trần Minh Thái
Email:
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 thông tin
Nắm vững và minh họa được giải thuật tìm
tuần tự và tìm kiếm nhị phân trên mảng một
chiều
Cài đặt được giải thuật tìm kiếm bằng ngôn
ngữ C/C++
2
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 xếp
3
Vấn đề tìm kiếm
Dựa vào một phần thơng tin được gọi là khố
(key) tìm một mẫu tin (record) chứa các
thơng tin khác liên quan với khố này
Có thể có nhiều mẫu tin hoặc khơng có mẫu
tin nào chứa khố cần tìm
4
Đánh giá giải thuật tìm kiếm
Tìm kiếm thường là tác vụ tốn nhiều thời gian trong
một chương trình
Tổ chức cấu trúc dữ liệu và giải thuật cho việc tìm
kiếm ảnh hưởng lớn đến hiệu suất hoạt động của
chương trình
Thơng số đo chủ yếu là số lần so sánh khoá cần tìm
với các mẫu tin khác
5
Phân loại
Tìm kiếm nội và tìm kiếm ngoại
Dữ liệu lưu trên thiết bị lưu trữ ngoài như đĩa
hay băng từ: tìm kiếm ngoại
Dữ liệu được lưu trữ trên bộ nhớ chính: tìm
kiếm nội
6
Các giải thuật tìm kiếm
Có 2 giải thuật thường được áp dụng: tìm
tuần tự và tìm nhị phân
Đặc tả:
a1
a2
a3
a4
a5
…
an-1 aN
Tập dữ liệu được lưu trữ là dãy số a1, a2, ... ,aN.
Khai báo: int a[N];
Khóa cần tìm: int x;
7
Tìm tuần tự (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 cho đến khi gặp được phần tử
cần tìm, hoặc hết mảng
8
Tìm tuần tự
Minh họa tìm x =10
10
7
5
12
41
10
32
13
9
15
3
1
2
3
4
5
6
7
8
9
10
Đã tìm
thấy
Chưa
hết tại
vịmảng
trí 5
Minh họa tìm x =25
Chưa
hết mảng
mảng
Đã hết
25
7
5
12
41
10
32
13
9
15
3
1
2
3
4
5
6
7
8
9
10
9
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.
10
Ngun 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
11
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ó khố x
}
12
Vấn đề
int LinearSearch(int a[], int N, int x)
{
Nếu có x thì khơng cần thiết
Có thể loại bỏ?
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ó khố x
}
13
Cải tiến
Dùng lính canh giúp giảm bớt phép so sánh
Minh họa tìm x =10
10
7
5
12
41
10
10
32
13
9
15
3
10
1
2
3
4
5
6
7
8
9
10
11
Minh họa tìm x = 25
25
7
5
12
41
10
32
13
9
15
3
25
25
1
2
3
4
5
6
7
8
9
10
11
14
Cài đặt
int LinearSearch2(int a[],int N,int x)
{
int i=0;
a[N] = x; // thêm phần tử x sau mảng
while (a[i]!=x )
i++;
if (i==N)
return -1; // tìm hết mảng
else
return i; // tìm thấy x tại vị trí i
}
Độ phức tạp tính tốn cấp n: T(n)=O(n)
15
Q&A
16
Tìm kiếm nhị phân (Binary Search)
Ý tưởng
Á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 hành để quyết định phạm vi
tìm kế tiếp
17
Minh họa tìm x = 41
x
x
x
3
14
16
19
22
41
46
51
63
71
1
2
3
4
5
6
7
8
9
10
l
Tìm thấy x tại vị trí 6
m
r
m
m
18
Minh họa tìm x = 45
x
x
x
x
3
14
16
19
22
41
46
51
63
71
1
2
3
4
5
6
7
8
9
10
l
m
m
r
l > r: Kết thúc: Khơng tìm
thấy
m
m
19
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: //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ử.
20
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;//Tìm thấy x tại vị trí 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
}
21
Bài tập
Cài đặt hàm tìm kiếm nhị phân bằng phương
pháp đệ quy?
22
Q&A
23
Code minh họa
#include <iostream.h>
#include<stdlib.h>
#include<time.h>
#define MAX 1000
void TaoMang(int a[], int N);
void XuatMang(int a[], int N);
int LinearSearch(int a[], int N, int x);
24
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: ”<
}
25