You are on page 1of 39

CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT

Mã môn học: IT003


Buổi 6

Số tiết lý thuyết: 45
Số tiết thực hành: 30
Số tiết tự học: 90

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
1
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
Chương 4: Tìm kiếm và Sắp xếp
Mục tiêu:
❖Xác định và phát biểu bài toán tìm kiếm - sắp xếp
❖ Hiểu một số thuật toán tìm kiếm và sắp xếp
❖ Phân tích ưu điểm và hạn chế của thuật toán tìm kiếm
và sắp xếp
❖ Triển khai, cài đặt các thuật toán với C++
❖ Biết các thuật ngữ tiếng Anh trong bài toán tìm kiếm
và sắp xếp
NỘI DUNG CHƯƠNG 4
4.1. Nhu cầu tìm kiếm, sắp xếp dữ liệu trong một hệ
thống thông tin
4.2 Định nghĩa bài toán tìm kiếm
4.3. Các giải thuật tìm kiếm:
- Tìm kiếm tuyến tính
- Tìm kiếm tuyến tính (cải tiến)
- Tìm kiếm nhị phân
- Tìm kiếm nội suy (Interpolation Search)
4.1 NHU CẦU TÌM KIẾM - SẮP XẾP
Trong thực tế, khai thác dữ liệu hầu như lúc nào
cũng phải thực hiện thao tác tìm kiếm.
Việc tìm kiếm nhanh hay chậm tùy thuộc vào trạng
thái và trật tự của dữ liệu.
Nếu dữ liệu trên mảng hay tập tin đã có thứ tự thì
thao tác tìm kiếm dữ liệu dễ dàng và nhanh chóng
hơn.
Thao tác sắp xếp dữ liệu là một trong những thao tác
cần thiết.
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
4
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
4.1 NHU CẦU TÌM KIẾM - SẮP XẾP
❖TRA CỨU THÔNG TIN
- Từ điển
4.1 NHU CẦU TÌM KIẾM - SẮP XẾP
❖TRA CỨU THÔNG TIN
- Truy vấn dữ liệu
4.1 NHU CẦU TÌM KIẾM - SẮP XẾP
❖TRA CỨU THÔNG TIN
- Soạn thảo, tra cứu văn bản
4.1 NHU CẦU TÌM KIẾM - SẮP XẾP

❖KẾT XUẤT DỮ LIỆU


- Sắp xếp các mục từ cho từ điển.
- Sắp xếp danh sách trong các báo cáo tổng hợp

→ Sắp xếp để thiết lập thứ tự cho danh sách, làm tăng hiệu
quả cho tìm kiếm.
4.2 BÀI TOÁN TÌM KIẾM

❖PHÁT BIỂU BÀI TOÁN


- Cho danh sách A gồm n phần tử a0, a1, .., an-1
Tìm phần tử có giá trị khóa là x trong A. Nếu ai có giá trị
khóa là x thì trả về chỉ số i
- Để đơn giản trong việc trình bày thuật toán ta
dùng mảng 1 chiều a để lưu danh sách các phần tử nói
trên trong bộ nhớ chính.
4.2 BÀI TOÁN TÌM KIẾM
Lưu ý:
Trong quá trình trình bày thuật toán ta dùng ngôn ngữ lập
trình C++.
Trình tự thực hiện:
➢ Ý tưởng thuật toán
➢ Biểu diễn thuật toán bằng mã giả
➢ Viết code cho thuật toán
➢ Minh họa
➢ Đánh giá độ phức tạp của thuật toán
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
10
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
4.3. CÁC GIẢI THUẬT TÌM KIẾM

a. Tìm kiếm tuyến tính


b. Tìm kiếm tuyến tính (cải tiến)
c. Tìm kiếm nhị phân
d. Tìm kiếm nội suy (Interpolation Search)

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
11
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
a. TÌM KIẾM TUYẾN TÍNH
Từ khóa: Linear Search

Điều kiện: Danh sách A = {a0, a1, .., an-1} chưa có thứ tự.

Phân tích: không có thông tin nào ngoài thông tin có được
khi so sánh x với giá trị khóa của ai

Ý tưởng: So sánh x lần lượt với phần tử thứ 1, thứ 2,…của


mảng a cho đến khi gặp được khóa cần tìm, hoặc tìm hết
mảng mà không thấy.
a. TÌM KIẾM TUYẾN TÍNH
• Thuật toán:
– Input: Danh sách A có n phần tử, giá trị khóa x cần tìm.
– Output: trả về 1 nếu tìm thấy, ngược lại, trả về 0 là không tìm thấy.
• Các bước tiến hành
➢Bước 1: Khởi gán i=0;
➢Bước 2: So sánh a[i] với giá trị x cần tìm, có 2 khả năng
+ (a[i] == x) : tìm thấy x. Dừng;
+ (a[i] != x) : sang bước 3;
➢Bước 3: i=i+1 // Xét phần tử kế tiếp 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;
a. TÌM KIẾM TUYẾN TÍNH

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


{
int i=0;
while ((i<n) && (a[i] != x)) i++;
if (i == n) return 0; // Không tìm thấy x
else return 1; // Tìm thấy x
}

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
14
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
Minh Họa Thuật Toán Tìm Kiếm Tuyến Tính

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

X=6

2 8 5 1 6 4 6

0 1 2 3 4 5 6

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
15
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
Minh Họa Thuật Toán Tìm Kiếm Tuyến Tính (tt)

i=7, không tìm thấy


X=10

2 8 5 1 6 4 6

0 1 2 3 4 5 6

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
16
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
Ðánh Giá Thuật Toán Tìm Tuyến Tính

Trường hợp Css

Tốt nhất 1

Xấu nhất n

Trung bình (n+1) / 2

➢ Độ phức tạp O(n)

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
17
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
VÍ DỤ 1:
Bài toán: Tìm phần tử là số nguyên tố lớn nhất có trong tam giác trên
đường chéo chính của ma trận ?
Đầu vào Thuật toán Đầu ra
A[n][n] void Tongtamgiactren(int A[][MAX], int n) - SNTMax
{ timthay = 0; - Hoặc Khong tim thay
for (int i=0;i<n-1;i++) SNT
for (int j=0;j<n-1;j++)
if ((i<j) && (ktsnt(A[i][j]))
{ timthay = 1;
SNTMax = A[i][j];
}
if (timthay)
{ for (int i=0;i<n-1;i++)
for (int j=0;j<n-1;j++)
if ((i<j) && (ktsnt(A[i][j])) SNTMax = A[i][j];
cout<<“ SNT Max: “<<SNTMax;
}
else cout<<“Khong tim thay SNT”;
}

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
18
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
VÍ DỤ 2:

Bài toán: Tìm một chuỗi con có trong một chuỗi lớn hay không ?
Nếu có, xác định vị trí được tìm thấy?
Đầu vào Thuật toán Đầu ra
chuoilon[50] gets(chuoilon); - timthay; vị trí
chuoicon[10] gets(chuoicon); timthay
i = 0; - hoặc không timthay.
timthay = 0;
while (chuoilon[i] != 0)
{ j = 0;
while ((chuoilon[i++] == chuoicon[j++]) &&
(chuoilon[i-1] != 0) && (chuoicon[j-1] != 0));
if ((chuoilon[i-1] != 0) && (chuoicon[j-1] == 0))
timthay = 1;
}
if (timthay) cout <<" Tim thay tai vi tri : "<< i-j;
else cout <<" Khong tim thay!";

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
19
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
a. TÌM KIẾM TUYẾN TÍNH
Cài đặt: (trên danh sách liên kết đơn)
Node* linearSearch(LIST l, int x)
{
Node *p = l.pHead;
while (!p && p->info != x) p = p->pNext;
if (p!=NULL) return 1;
else return NULL;
}
b. Cải Tiến Thuật Toán Tìm Tuyến Tính
Nhận xét::
➢ Để giảm thiểu số phép so sánh trong vòng
➢ Số phép so sánh của thuật toán trong lặp cho thuật toán, ta thêm phần tử “lính
trường hợp xấu nhất là 2*n. canh” vào cuối dãy.

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


{ {
int i=0; int i=0;
while ((i<n) && (a[i] != x)) i++; a[n]=x; // a[n] là phần tử “lính canh”
if (i == n) return 0; // Không thấy x while (a[i] != x) i++;
else return 1; // Tìm thấy x if (i == n) return 0; // Không thấy x
} else return 1; // Tìm thấy
}

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
21
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
c. TÌM KIẾM NHỊ PHÂN

Từ khóa: Binary Search

Điều kiện: Danh sách A = {a0, a1, .., an-1} đã có thứ tự

Phân tích: Khi so sánh ai với khóa x, dựa vào quan hệ


thứ tự, có thể quyết định nên xét phần tử kế tiếp ở phần
trước (hoặc phần sau) của ai hay không?
c. TÌM KIẾM NHỊ PHÂN
➢ Áp dụng cho mảng đã được sắp xếp có thứ tự (tăng hay giảm).
▪ Giả xử ta xét mảng có thứ tự tăng, khi ấy ta có ai-1<ai<ai+1
▪ Nếu x>ai thì x chỉ có thể xuất hiện trong đoạn [ai+1, an-1]
▪ Nếu x<ai thì x chỉ có thể xuất hiện trong đoạn [a0, ai-1]
➢ Ý tưởng:
▪ Tại mỗi bước, ta so sánh x với phần tử đứng giữa trong dãy
đang tìm kiếm hiện hành.
▪ Dựa vào kết quả so sánh này mà ta quyết định giới hạn dãy
tìm kiếm là ở nửa trước hay nửa sau của dãy hiện hành.

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
23
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
Các Bước Thuật Toán Tìm Kiếm Nhị Phân
• Giả sử dãy tìm kiếm hiện hành là các phần tử trong đoạn [aleft, aright],
các bước của thuật toán là:
– Bước 1: left = 0; right = n-1;
– Bước 2:
▪ mid = (left+right)/2; //chỉ số phần tử giữa dãy hiện hà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 : right= mid-1;
• a[mid] < x : left= mid+1;
– Bước 3: Nếu left <=right : // còn phần tử trong dãy hiện hành
+ Lặp lại bước 2;
+ Ngược lại : không tìm thấy. Dừng.
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
24
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
Cài Đặt Thuật Toán Tìm Nhị Phân
• Hàm trả về 1 nếu tìm thấy, ngược lại, không tìm thấy trả về 0.

int BinarySearch(int a[], int n, int x)


{ int mid, left = 0, right = n-1;
do
{ mid = (left + right) / 2;
if (a[mid] == x) return 1; // tìm thấy
else if (a[mid] < x) left = mid+1;
else right = mid-1;
} while (left <= right);
return 0; // không tìm thấy
}
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
25
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
Minh Họa Thuật Toán Tìm Nhị Phân

Tìm thấy 2 tại vị trí 1

X=2

L M R

1 2 4 6 7 9 10

0 1 2 3 4 5 6

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
26
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
Minh Họa Thuật Toán Tìm Nhị Phân (tt)

X=-1

L M R

1 2 4 6 7 9 10

0 1 2 3 4 5 6

L=0
R=-1 => không tìm thấy X=-1

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
27
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
Ðánh Giá Thuật Toán Tìm nhị phân

Trường hợp Css


Tốt nhất 1

Xấu nhất log2n


Trung bình log2n / 2

➢ Độ phức tạp O(log2n)

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
28
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
Đánh giá độ phức tạp thuật toán

❖ Trường hợp xấu nhất: O(log2n)

▪ Phân hoạch dãy số n phần tử thành 2 phần. Thực hiện việc


so sánh x với phần tử chính giữa.

➢Lần thứ 1: n/2

➢Lần thứ 2: (n/2)/2 = n / 22

➢….

➢Lần thứ k: n/2k

▪ Sau k lần phân hoạch : n = 2k => log2(n) = log2(2k) = k


TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
29
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
d. TÌM KIẾM NỘI SUY

Từ khóa: Interpolation Search

Điều kiện: Danh sách A = {a0, a1, .., an-1} đã có thứ tự


 và giá trị khóa được rải đều trên danh sách.

Phân tích: Giá trị khóa rải đều trên danh sách → vị trí
am chia danh sách tìm kiếm tương ứng với tỉ lệ giá trị x
trong miền giá trị khóa của danh sách tìm kiếm.
d. TÌM KIẾM NỘI SUY

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN, KHU PHỐ 6, PHƯỜNG LINH TRUNG, QUẬN THỦ ĐỨC, TP. HỒ CHÍ MINH
31
[T] 08 3725 2002 101 | [F] 08 3725 2148 | [W] www.uit.edu.vn | [E] info@uit.edu.vn
d. TÌM KIẾM NỘI SUY

Thuật toán:
Đầu vào: Danh sách A có n phần tử đã có thứ tự
, giá trị khóa x cần tìm.
Đầu ra: Chỉ số i của phần tử ai trong A có giá trị
khóa là x. Trong trường hợp không tìm thấy i=-1
d. TÌM KIẾM NỘI SUY

Thuật toán:

l  0, r  n-1
while l  r
m  l+((r-l)*(x-a[l]) / (a[r]-a[l]))
if x = a[m] then return m end if
if x  a[m] then r  m – 1
else l  m + 1 end if
end while
return -1
d. TÌM KIẾM NỘI SUY
Quá trình tính toán:
Giả sử A = {1,2,3,4,5,7,9}, thứ tự  là <, phần tử
cần tìm x = 3

l=0 m=1 2
3 4 5 r=6
1 2 3 4 5 7 9

x=3
d. TÌM KIẾM NỘI SUY

Quá trình tính toán:


Giả sử A = {1,2,3,4,5,7,9}, thứ tự  là <, phần tử
cần tìm x = 3

m=2
0 1 l=2 3 4 5 r=6
1 2 3 4 5 7 9

x=3 m=2
a[m] = 3 = x
d. TÌM KIẾM NỘI SUY

Cài đặt: (trên mảng, thứ tự  là <)


int interpolationSearch (int a[],int n,int x)
{
int l = 0, r = n-1;
while (l <= r)
{
m = l+(r-l)*(x-a[l])/(a[r]-a[l]);
if (x == a[m]) return m;
if (x < a[m]) r = m – 1;
else l = m + 1;
}
return -1;
}
BÀI TẬP

1) Cho danh sách A={1,2,3,4,5,6,100000} được lưu


trữ trên mảng.
a) Cho biết thuật toán tốt nhất để tìm giá trị x trong
A. Vì sao?
b) Trình bày từng bước quá trình tìm giá trị x=6
trong A theo thuật toán đã chọn.
c) Giả sử A được lưu trữ trên danh sách liên kết
đơn. Cho biết thuật toán tốt nhất để tìm giá trị x
trong A. Vì sao?
BÀI TẬP

2) Viết hàm tìm kiếm phần tử x trên mảng A chứa n


số nguyên. Biết A đang có thứ tự > (giảm dần) và
chưa biết phân bố giá trị của các phần tử trong A.
BÀI TẬP
3) Cho cấu trúc điểm trong mặt phẳng như sau:
struct Point
{
float x, y;
};
Viết hàm tìm kiếm điểm q(xq,yq) trong danh sách các
điểm A (A được lưu trữ trên mảng) sao cho khoảng
cách giữa q và p(xp,yp) là nhỏ nhất. Trong đó p là một
điểm cho trước (tham số của hàm tìm kiếm). Kết quả
trả về là chỉ số của q trong A.

You might also like