Chương 2.1. Giải thuật tìm kiếm

Tr n Minh Thái Email: minhthai@huflit.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 tuần tự và tìm kiếm

thông tin

• Cài đặt được giải thuật tìm kiếm bằng ngôn ngữ C/C++

2

nhị phân trên mảng một chiều

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

3

xếp

Vấn đề tìm kiếm

• Dựa vào một phần thông tin được gọi là khoá (key)  tìm một

• Có thể có nhiều mẫu tin hoặc không có mẫu tin nào chứa

mẫu tin (record) chứa các thông tin khác liên quan với khoá này

4

khoá cần tìm

Đá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

 Tổ chức cấu trúc dữ liệu và giải thuật cho việc tìm kiếm ảnh

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

hưởng lớn đến hiệu suất hoạt động của chương trình

5

mẫu tin khác

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

• Dữ liệu được lưu trữ trên bộ nhớ chính: tìm kiếm nội

6

kiếm ngoại

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ị

• Đặ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;

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

8

cho đến khi gặp được phần tử cần tìm, hoặc hết mảng

Tìm tuần tự

• 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

7 1

5 2

12 3

41 4

10 5

32 6

13 7

9 8

15 9

3 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

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

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ó khoá 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ó khoá x

13

}

Cải tiến

• Minh họa tìm x =10

Dùng lính canh giúp giảm bớt phép so sánh

10

10

12 3

7 1

10 10 5

32 6

13 7

15 9

3 10

9 8

11

41 5 4 2 • Minh họa tìm x = 25

25

5 2

12 3

41 4

10 5

32 6

13 7

3 10

15 9

7 1

9 8

25 25 11

14

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)

15

Cài đặt int LinearSearch2(int a[],int N,int x) {

Q & A

16

Tìm kiếm nhị phân (Binary Search)

• Á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

17

hành để quyết định phạm vi tìm kế tiếp

Minh họa tìm x = 41

x

x

x

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

Tìm thấy x tại vị trí 6

l

m

m

r

m

18

Minh họa tìm x = 45

x

x

x

x

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

l

m

m

r

l > r: Kết thúc: Không tìm thấy

m

m

19

//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

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;//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

} Độ phức tạp tính toán cấp n: T(n)=O(log 2n)

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

#include

#include

#define MAX 1000

void TaoMang(int a[], int N);

void XuatMang(int a[], int N);

24

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: ”<

25

}

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<

26

}

int LinearSearch(int a[], int N, int x)

{

int i=0;

while ((i

i++;

if(i==N)

return -1;

else

return i;

}

27

Bài tập áp dụng

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:

28

tuyến tính và nhị phân

Bài tập lý thuyết

• 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.

29

trong dãy số: Dùng mã tự nhiên, mã giả và lưu đồ.

Q & A

30