Tải bản đầy đủ (.pdf) (95 trang)

Slide bài giảng cấu trúc dữ liệu

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.82 MB, 95 trang )

ð
ð


i H
i H


c Sư Ph
c Sư Ph


m Tp. H
m Tp. H


Ch
Ch
í
í
Minh
Minh
Chương 2: Tìm kiếm & Sắp xếp
C
C


U TR
U TR
Ú
Ú


C D
C D


LI
LI


U 1
U 1
2
2
Thông tin giảng viên


LƯƠNG TR
LƯƠNG TR


N HY HI
N HY HI


N
N
• Bộ Môn Tin Học
• Khoa Toán – Tin học
• Phone:
0989 366 990
0989 366 990

• Email:
3
3
Tìm kiếm & Sắp xếp
Mục tiêu:
• Giới thiệu một số thuật toán tìm kiếm và sắp xếp nội.
• Phân tích, đánh giá độ phức tạp của các giải thuật tìm
kiếm, sắp xếp.
Nội dung:
• Nhu cầu tìm kiếm và sắp xếp dữ liệu trong một hệ
thống thông tin.
• Các giải thuật tìm kiếm nội.
• Các giải thuật sắp xếp nội.
4
4
Các giải thuật
tìm kiếm nội
• Tìm tuần tự
• Tìm nhị phân
Tìm kiếm
5
5
Các giải thuật tìm kiếm nội
Bài toán: Tìm vò trí xuất hiện của phần tử có
giá trò
x trên danh sách đặc a
•Tập dữ liệu được lưu trữ là dãy số a
1
, a
2

, ... ,a
N
int a[N];
•Khoá cần tìm là x
int x;
6
6
Tìm kiếm tuần tự
• Bước 1: i = Vò trí đầu;
• Bước 2: Nếu
a[i] = x : Tìm thấy. Dừng, vò trí
xuất hiện: i
• Bước 3 : i = Vò trí kế(i);// xét tiếp phần tử kế
trong mảng
• Bước 4: Nếu i >Vò trí cuối: //Hết mảng
Không tìm thấy. Dừng.
Ngược lại: Lặp lại Bước 2.
7
7
Tìm kiếm tuần tự
• Ví dụ: Cho dãy số a
12 2 8 5 1 6 4 15
• Giá trò cần tìm: 8
• i = 1
8
8
Tìm kiếm tuần tự
• i = 2
• i = 3
9

9
T
TT

ìì
ìm kie
m kiem kie
m kiế
áá
ám tua
m tuam tua
m tuầ
àà
àn t
n tn t
n tự
ựự

int LinearSearch(int a[], int N, int x)
{
for (int i=0; (i<N)&&(a[i]!=x ); i++);
if (i<N)
return i; // a[i] là phần tử có khoá x
return -1; // tìm hết mảng nhưng không có x
}
10
10
Tìm kiếm tuần tự
• Cải tiến cài đặt: dùng phương pháp “đặt lính
canh


– Đặt thêm một phần tử có giá trò x vào cuối mảng
– Bảo đảm luôn tìm thấy x trong mảng
– Sau đó dựa vào vò trí tìm thấy để kết luận.
11
11
Tìm kiếm tuần tự
int LinearSearch(int a[], int N, int x)
{
// mảng gồm N phần tử từ a[0]..a[N-1]
a[N] = x; // thêm lính canh vào cuối dãy
for (int i=0; (a[i]!=x); i++);
if (i<N)
return i; // a[i] là phần tử có khoá x
return -1; // tìm hết mảng nhưng không có x
}
12
12
Tìm kiếm tuần tự
• Đánh giá giải thuật:
• Vậy giải thuật tìm tuần tự có độ phức tạp
tính toán cấp n: T(n) = O(n)
13
13
Tìm kiếm tuần tự

Nhận xét:
– Giải thuật tìm tuyến tính không phụ thuộc vào
thứ tự của các phần tử trong danh sách, do vậy
đây là phương pháp tổng quát nhất để tìm kiếm

trên một danh sách bất kỳ.
– Một thuật toán có thể được cài đặt theo nhiều
cách khác nhau, kỹ thuật cài đặt ảnh hưởng đến
tốc độ thực hiện của thuật toán.
14
14
Tìm kiếm nhò phân
• Đối với những dãy đã sắp thứ tự (giả sử thứ tự
tăng), các phần tử trong dãy có quan hệ
a
i -1

≤≤
≤ a
i

≤≤
≤ a
i+1
Nếu x > a
i
thì x chỉ có thể xuất hiện trong
đoạn
[a
i+1
,a
N
] của dãy
Nếu x < a
i

thì x chỉ có thể xuất hiện trong
đoạn
[a
1
,a
i-1
] của dãy
15
15
Tìm kiếm nhò phân
• Ý tưởng của giải thuật là 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 giới hạn dãy tìm
kiếm ở bước kế tiếp là nửa trên hay nửa dưới
của dãy tìm kiếm hiện hành
16
16
Tìm kiếm nhò phân
Bước 1: left = VTĐ; right = VTC;
Bước 2: Trong khi left ≤
≤≤
≤ right lặp: //đoạn tìm kiếm chưa rỗng
Bước 21: mid = (left+right)/2; // lấy mốc so sánh
Bước 22: Nếu a[mid] = x: //Tìm thấy.
Dừng, vò trí xuất hiện: mid
Bước 23: Nếu a[mid] > x: //tìm x trong dãy con a
left
.. a

mid -1
right = mid - 1;
Ngược lại //tìm x trong dãy con a
mid +1
.. a
right
left = mid + 1;
//Hết lặp
Bước 3: Dừng, không tìm thấy.
17
17
Tìm kiếm nhò phân
• Ví dụ: Cho dãy số a gồm 8 phần tử:
1 2 4 5 6 8 12 15
• Giá trò cần tìm là 8
18
18
Tìm kiếm nhò phân
• left = 1, right = 8, mid = 4
19
19
Tìm kiếm nhò phân
• left = 5, right = 8, mid = 6
20
20
Tìm kiếm nhò phân
int BinarySearch(int a[],int N,int x )
{
int left =0, right = N-1, midle;
while (left <= right)

{
midle = (left + right)/2;
if (x == a[midle])
return midle;//Tìm thấy x tại mid
if (x<a[midle])right = midle -1;
else left = midle +1;
}
return -1; // trong dãy không có x
}
21
21
Tìm kiếm nhò phân
• Đánh giá giải thuật:
• Giải thuật tìm nhò phân có độ phức tạp
tính toán cấp logn:
T(n) = O(log
2
n)
22
22
Tìm kiếm nhò phân

Nhận xét:
– Giải thuật tìm nhò phân dựa vào quan hệ giá trò
của các phần tử mảng để đònh hướng trong quá
trình tìm kiếm, do vậy chỉ áp dụng được cho
những dãy đã có thứ tự.
– Giải thuật tìm nhò phân tiết kiệm thời gian hơn
rất nhiều so với giải thuật tìm tuần tự do
T

nhò phân
(n) = O(log
2
n) < T
tuần tự
(n) = O(n).
23
23
Tìm kiếm nhò phân

Nhận xét:
– Khi muốn áp dụng giải thuật tìm nhò phân cần
phải xét đến thời gian sắp xếp dãy số để thỏa
điều kiện dãy số có thứ tự. Thời gian này không
nhỏ, và khi dãy số biến động cần phải tiến hành
sắp xếp lại => khuyết điểm chính cho giải thuật
tìm nhò phân.
– Cần cân nhắc nhu cầu thực tế để chọn một trong
hai giải thuật tìm kiếm trên sao cho có lợi nhất.
24
24
Đònh nghóa bài toán sắp xếp
• Sắp xếp là quá trình xử lý một danh sách các
phần tử (hoặc các mẫu tin) để đặt chúng theo
một
thứ tự thỏa mãn một tiêu chuẩn nào đó
dựa trên nội dung thông tin lưu giữ tại mỗi
phần tử.
• Lưu ý: Thứ tự được đề cập ở đây là một thứ
tự tổng quát.

• Ví dụ: Hãy đònh nghóa một thứ tự để dãy số
sau là dãy tăng theo thứ tự này.
1 3 5 7 22 20 10 6
25
25
Khái niệm nghòch thế
• Khái niệm nghòch thế:
– Xét một mảng các số a
0
, a
1
, … a
n
.
– Nếu có i<j và a
i
> a
j
, thì ta gọi đó là một nghòch
thế.
• Mảng chưa sắp xếp sẽ có nghòch thế.
• Mảng đã có thứ tự sẽ không chứa nghòch thế.
a
0

≤≤
≤ a
1

≤≤

≤ … ≤
≤≤
≤ a
n
26
26
Các phương pháp sắp xếp thông dụng
• Selection sort
• Insertion sort
• Interchange sort
• Bubble sort
• Shaker sort
• Binary Insertion
sort
• Shell sort
• Heap sort
• Quick sort
• Merge sort
• Radix sort
• …
Đ
Đ
ơn gia
ơn gia
û
û
n,
n,
Chi ph
Chi ph

í
í
cao
cao
Ph
Ph


c ta
c ta
ï
ï
p hơn
p hơn
Hie
Hie
ä
ä
u qua
u qua
û
û
cao
cao


ù
ù
p thua
p thua

ä
ä
t toa
t toa
ù
ù
n
n
kha
kha
ù
ù
c
c
27
27
Selection sort – Ý tưởng
• Nhận xét: Mảng có thứ tự thì
a
i
= min(a
i
, a
i+1
, …, a
n-1
)


Ý tưởng: mô phỏng một trong những cách sắp

xếp tự nhiên nhất trong thực tế:
– Chọn phần tử nhỏ nhất trong N phần tử ban đầu,
đưa phần tử này về vò trí đúng là đầu dãy hiện
hành
– Xem dãy hiện hành chỉ còn N-1 phần tử của dãy
ban đầu, bắt đầu từ vò trí thứ 2; lặp lại quá trình
trên cho dãy hiện hành... đến khi dãy hiện hành
chỉ còn 1 phần tử.
28
28
Selection sort – Thuật toán
//input: dãy (a, N)
//output: dãy (a, N) đã được sắp xếp
• Bước 1 : i = Vò trí đầu;
• Bước 2 : Tìm phần tử a[min] nhỏ nhất trong dãy
hiện hành từ a[i] đến a[N]
• Bước 3 : Nếu min

≠≠
≠ i: Hoán vò a[min] và a[i]
• Bước 4 : Nếu i chưa là Vò trí cuối
» i = Vò trí kế(i);
» Lặp lại Bước 2
Ngược lại: Dừng. //N phần tử đã nằm
đúng vò trí.
29
29
Selection sort – Ví duï
2 8 5 1 6 4 1512
i

min
2 3 4 5 6 7 81
Find MinPos(1, 8)
Swap(a
i
, a
min
)
30
30
Selection sort – Ví duï
2 8 5 12 6 4 151
i
min
2 3 4 5 6 7 81
Find MinPos(2, 8)
Swap(a
i
, a
min
)
31
31
Selection sort – Ví duï
2 8 5 12 6 4 151
i
min
2 3 4 5 6 7 81
Find MinPos(3, 8)
Swap(a

i
, a
min
)
32
32
Selection sort – Ví duï
2 4 5 12 6 8 151
i
min
2 3 4 5 6 7 81
Find MinPos(4, 8)
Swap(a
i
, a
min
)
33
33
Selection sort – Ví duï
2 4 5 12 6 8 151
i
min
2 3 4 5 6 7 81
Find MinPos(5, 8)
Swap(a
i
, a
min
)

34
34
Selection sort – Ví duï
2 4 5 6 12 8 151
i
min
2 3 4 5 6 7 81
Find MinPos(6, 8)
Swap(a
i
, a
min
)
35
35
Selection sort – Ví dụ
2 4 5 6 8 12 151
i
min
2 3 4 5 6 7 81
Find MinPos(7, 8)
Swap(a
i
, a
min
)
12
15
36
36

Selection sort
void SelectionSort(int a[],int N )
{
int min; // chỉ số phần tử nhỏ nhất trong dãy hiện hành
for (int i=0; i<N-1 ; i++)
{
min = i;
for(int j = i+1; j < N ; j++)
if (a[j] < a[min])
min = j; // ghi nhận vò trí phần tử nhỏ nhất
if (min != i)
Swap(a[min], a[i]);
}
}
37
37
• Số lần hoán vò (một hoán vò bằng 3 phép
gán) phụ thuộc vào tình trạng ban đầu
của dãy số
Selection sort – Đánh giá giải thuật
38
38
Selection sort – Đánh giá giải thuật
• Ởû lượt thứ i, cần (N-i) lần so sánh để xác
đònh phần tử nhỏ nhất hiện hành.
• Số lượng phép so sánh không phụ thuộc vào
tình trạng của dãy số ban đầu.
• Trong mọi trường hợp, số lần so sánh là:
2
1)n(n

i)(n
1n
1i

=−


=
39
39
Insertion Sort – Ý tưởng
• Nhận xét: mọi dãy a
1
, a
2
,..., a
n
luôn có i-1 phần tử
đầu tiên a
1
, a
2
,... ,a
i-1
đã có thứ tự (2 ≤ i).


Ý tưởng chính: tìm cách chèn phần tử a
i
vào vò trí

thích hợp của đoạn đã được sắp để có dãy mới a
1
,
a
2
,... ,a
i
trở nên có thứ tự.
– Vò trí này chính là pos thỏa a
pos-1
≤ a
i
< a
pos
(1≤
≤≤
≤pos≤
≤≤
≤i).
Chi tiết hơn:
– Dãy ban đầu a
1
, a
2
,..., a
n
, xem như đã có đoạn gồm một
phần tử a
1
đã được sắp.

– Thêm a
2
vào đoạn a
1
sẽ có đoạn a
1
a
2
được sắp
– Thêm a
3
vào đoạn a
1
a
2
để có đoạn a
1
a
2
a
3
được sắp
– Tiếp tục cho đến khi thêm xong a
N
vào đoạn a
1
a
2 ...
a
N-1

sẽ
có dãy a
1
a
2....
a
N
được sắp.
40
40
Insertion Sort – Thuật toán
//input: dãy (a, N)
//output: dãy (a, N) đã được sắp xếp
• Bước 1
: i = 2; // giả sử có đoạn a[1] đã được sắp
• Bước 2
: x = a[i]; Tìm vò trí pos thích hợp trong đoạn
a[1]
đến a[i] để chèn x vào
• Bước 3
: Dời chỗ các phần tử từ a[pos] đến a[i-1] sang
phải 1 vò trí để dành chổ cho x
• Bước 4
: a[pos] = x; // có đoạn a[1]..a[i] đã được sắp
• Bước 5
: i = i+1;
Nếu i ≤
≤≤
≤ n : Lặp lại Bước 2.
Ngược lại : Dừng.

41
41
Insertion Sort – Ví duï
2 8 5 1 6 4 1512
2 3 4 5 6 7 81
42
42
2 8 5 1 6 4 1512
i
x
2 3 4 5 6 7 81
pos
2
Insertion Sort – Ví duï
Insert a
2
into (1, 2)
43
43
12 8 5 1 6 4 152
i
x
2 3 4 5 6 7 81
pos
Insertion Sort – Ví duï
Insert a
3
into (1, 3)
8
44

44
8 12 5 1 6 4 152
i
x
2 3 4 5 6 7 81
pos
Insertion Sort – Ví duï
Insert a
4
into (1, 4)
5
45
45
5 8 12 1 6 4 152
i
x
2 3 4 5 6 7 81
pos
Insertion Sort – Ví duï
Insert a
5
into (1, 5)
1
46
46
2 5 8 12 6 4 151
i
x
2 3 4 5 6 7 81
pos

Insertion Sort – Ví duï
Insert a
6
into (1, 6)
6
47
47
2 5 6 8 12 4 151
i
x
2 3 4 5 6 7 81
pos
Insertion Sort – Ví duï
Insert a
7
into (1, 7)
4
48
48
2 4 5 6 8 12 151
i
x
2 3 4 5 6 7 81
pos
Insertion Sort – Ví duï
Insert a
8
into (1, 8)
15
49

49
2 4 5 6 8 12 151
pos
2 3 4 5 6 7 81
Insertion Sort – Ví dụ
50
50
Insertion Sort – Cài đặt
void InsertionSort(int a[], int N )
{
int pos, i;
int x;
//lưu trữ a[i] tránh bò ghi đè khi dời chỗ các phần tử.
for(int i=1 ; i<N ; i++) //đoạn a[0] đã sắp
{
x = a[i];
for(pos=i;(pos>0)&&(a[pos-1]>x);pos--)
a[pos] = a[pos-1];
a[pos] = x;// chèn x vào dãy
}
}

×