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
kiếm tuyến tính 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++
22 trang |
Chia sẻ: thuychi16 | Lượt xem: 1028 | Lượt tải: 1
Bạn đang xem trước 20 trang tài liệu Cơ sở dữ liệu - Chương 2: Giải thuật tìm kiếm, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Chương 2.1. Giải thuật
tìm kiếm
Võ Quang Hoàng Khang
Email: vqhkhang@gmail.com
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
kiếm tuyến tính 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
Suy nghĩ
3
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?
?
Nhu cầu tìm kiếm và sắp xếp
Thao tác tìm kiếm được sử dụng nhiều nhất trong các
hệ lưu trữ và quản lý dữ liệu.
Do dữ liệu lớn nên tìm ra giải thuật tìm kiếm nhanh
chóng là mối quan tâm hàng đầu. Để đạt được điều
này dữ liệu phải được tổ chức theo một thứ tự nào đó
thì việc tìm kiếm sẽ nhanh chóng và hiệu quả hơn, vì
vậy nhu cầu sắp xếp dữ liệu cũng được lưu ý.
Tóm lại, bên cạnh những giải thuật tìm kiếm thì các
giải thuật sắp xếp dữ liệu không thể thiếu trong hệ
quản lý thông tin trên máy tính.
4
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ị phân.
Đặc tả như sau:
Tập dữ liệu được lưu trữ là dãy số a1, a2, ... ,aN.
Giả sử chọn cấu trúc dữ liệu mảng để lưu trữ dãy
số này trong bộ nhớ chính, có khai báo: int a[N];
Khoá cần tìm là x, được khai báo như sau: int x;
5
a1 a2 a3 a4 a5 an-1 aN
Tìm kiếm tuyến tính
Ý 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 đã tìm hết mảng mà không thấy x
Minh họa tìm x =10
Minh họa tìm x =25
6
Chưa hết
mảng
7 5 12 41 10 32 13 9 15 3
1 2 3 4 5 6 7 8 9 10
7 5 12 41 10 32 13 9 15 3
1 2 3 4 5 6 7 8 9 10
10
25
Chưa
hết
mảng
Đã tìm
thấy ại
vị trí 5
Đã hết
mảng
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.
7
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
8
Cài đặt
int TimTuyenTinh(int a[], int N, int x)
{
int i=0;
while ((i<N) && (a[i]!=x ))
{
i++;
}
if(i==N)
return -1; //tìm hết mảng
else
return i; //a[i] là phần tử có khoá x
} 9
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
Minh họa tìm x = 25
10
7 5 12 41 10 32 13 9 15 3
1 2 3 4 5 6 7 8 9 10
10
7 5 12 41 10 32 13 9 15 3
1 2 3 4 5 6 7 8 9 10
25
11
25
25
10
11
Cài đặt
int TimTuyenTinh2(int a[],int N,int x)//cải tiến
{ 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 toán cấp n: T(n)=O(n)
11
Tìm kiếm nhị phân
Ý tưởng
Áp dụng đối với những dãy số đã có thứ tự.
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
phạm vi tìm kiếm ở bước kế tiếp.
12
Minh họa tìm x = 41
13
3 14 16 19 22 41 46 51 63 71
1 2 3 4 5 6 7 8 9 10
x
ml m
x
r
m
x
Tìm thấy x tại
vị trí 6
Minh họa tìm x = 45
14
3 14 16 19 22 41 46 51 63 71
1 2 3 4 5 6 7 8 9 10
x
m m
x
r
m
x
l
m
x
l > r: Kết thúc:
Không tìm thấy
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ử. 15
int TimNhiPhan( 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
}
Độ phức tạp tính toán cấp n: T(n)=O(log 2n)
16
Code minh họa
#include
#include
#include
#define MAX 1000
void TaoMang(int a[], int N);
void XuatMang(int a[], int N);
int LinearSearch(int a[], int N);
17
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: ”<<kq;
}
18
void TaoMang(int a[], int N)
{
for(int i=0; i<N; i++)
a[i]=rand()%N;
}
void XuatMang(int a[], int N)
{
for(int i=0; i<N; i++)
cout<<a[i]<<“ “;
}
19
int LinearSearch(int a[], int N, int x)
{
int i=0;
while ((i<N) && (a[i]!=x ))
i++;
if(i==N)
return -1;
else
return i;
}
20
Bài tập lý thuyết
LT1_1: Cho dãy số sau:
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.
LT1_2: Xây dựng giải thuật tìm kiếm phần tử
có giá trị nhỏ nhất trong dãy số: Dùng mã tự
nhiên, mã giả và lưu đồ.
21
3 4 6 6 12 16 21 34 41 80
0 1 2 3 4 5 6 7 8 9
Bài tập viết chương trình
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: tuyến tính và nhị phân
22