SlideShare a Scribd company logo
1 of 81
Download to read offline
1
TÌM KIẾM & SẮP XẾP
2
Tìm kiếm
Tìm kiếm tuần tự
Tìm kiếm nhị phân
3
Ví dụ – Tìm vị trí X trong dãy
//input: dãy (a, N), X
//output: Vị trí của X, -1 nếu không có
intint Search(int a[], int N, int X)Search(int a[], int N, int X)
{{
for (int i = 0; i < N; i ++)for (int i = 0; i < N; i ++)
if (a[i] == X)if (a[i] == X)
return i;return i;
returnreturn --1;1;
}}
Bài toán: Tìm vị trí X trên mảng a đang có N
thành phần.
Giải pháp: Tìm tuần tự
4
Tìm kiếm
Tìm kiếm tuần tự (tìm kiếm tuyến tính)
– Thời gian tồi nhất để thực hiện giải thuật:n x constant
– Tỷ suất tăng của giải thuật là n
– Độ phức tạp thuật toán O(n)
5
Ứng dụng – Loại bỏ một thành phần dữ liệu
Bài toán: loại bỏ thành phần dữ liệu X
ra khỏi mảng a đang có N thành phần.
Hướng giải quyết: xác định vị trí của
X, nếu tìm thấy thì dồn các phần tử ở
phía sau lên để lấp vào chỗ trống. 2
trường hợp:
– Dãy không có thứ tự: lấp phần tử cuối lên
– Dãy đã thứ tự: dời tất cả các phần tử ở
sau ví trí của X lên trước 1 vị trí.
6
N = 8
Ứng dụng – Loại bỏ X ra khỏi dãy tăng
Loại 5 khỏi (a, 8)
N = 7
pos
Tìm vị trí của 5
X
Dồn các vị trí 4, 5, 6, 7 lên
7
Ứng dụng – Loại bỏ X ra khỏi dãy tăng
//input: dãy (a, N), X
//output: dãy (a, N) đã loại bỏ 1 thành phần X
intint Remove(int a[], int &N, int X)Remove(int a[], int &N, int X)
{{
int pos = Search(a, N, X);int pos = Search(a, N, X);
if (pos ==if (pos == --1)1) //không c//không cóó X trong dãyX trong dãy
return 0;return 0;
NN ----;;
for (; (pos < N); pos ++)for (; (pos < N); pos ++)
a[pos] = a[pos + 1];a[pos] = a[pos + 1];
return 1;return 1;
}}
8
Tìm kiếm
Tìm kiếm nhị phân
– Bài toán: Với một dãy số đã sắp xếp, chúng ta có thể
áp dụng phương pháp tìm kiếm nhị phân.
9
Tìm kiếm nhị phân
Phương pháp tìm:ứng dụng cho các dãy đã
sắp xếp thứ tự
Kiểm tra phần tử giữa của dãy
– Nếu khóa cần tìm nhỏ hơn, tiến sang trái
– Nếu trùng khớp: Kết thúc!
– Nếu khóa cần tìm lớn hơn, tiến sang phải
Bạn có thể chia n thành hai phần: tốn thời gian log2n
Bởi vậy tìm kiếm nhị phân tốn thời gian = c log2n
Độ phức tạp tính toán của thuật toán là O( log n )
n
n
2
<
n
4
n
8
10
Ví dụ – Tìm vị trí X trong dãy
//input: dãy (a, N), X
//output: Vị trí của X, -1 nếu không có
intint BinarySearch(int a[], int N, int x)BinarySearch(int a[], int N, int x)
{int left=0, right=N{int left=0, right=N--1, mid;1, mid;
do{do{
mid=(left+right)/2;mid=(left+right)/2;
if(x==a[mid]) return mid;// x tai midif(x==a[mid]) return mid;// x tai mid
else if (x<a[mid]) right=midelse if (x<a[mid]) right=mid--1;1;
else left= mid+1;else left= mid+1;
}while (left<=right);}while (left<=right);
returnreturn --1;1;
}}
Bài toán: Tìm vị trí X trên mảng a đang có N
thành phần ( mảng a sắp tăng dần).
Giải pháp: Tìm nhị phân
11
Tìm kiếm tuần tự & Tìm kiếm nhị phân
Chọn lựa phương pháp
– Tuần tự:Thời gian thực hiện tồi nhất: c1 n
– Tìm kiếm nhị phân:Thời gian thực hiện tồi nhất: c2 log2n
Compare n with logn
0
10
20
30
40
50
60
0 10 20 30 40 50 60
n
Time
4 log n
n
Bài toán nhỏ -
Chúng tôi
không quan
tâm!
Các
bài
toán
lớn -
Nhận
thấy
TK nhị
phân
tốt
hơn
nhiều
n
4log2nVới bài toán
nhỏ: Tìm kiếm
nhị phân có T(n)
cao hơn
12
Tìm kiếm
Tìm kiếm tuần tự
– Tỷ suất tăng: n
– Độ phức tạp thuật toán: O(n)
– Được sử dụng tốt cho các dãy chưa sắp xếp
Tìm kiếm nhị phân
– Cho các dãy đã sắp xếp
– Tỷ suất tăng: log2 n
– Độ phức tạp: O(log n)
Trường hợp dãy chưa sắp xếp: phải cộng thêm chi phí sắp
xếp dãy, do đó (không nên dùng tìm kiếm nhị phân)
13
SẮP XẾP
14
Mục tiêu
Sau khi hoàn tất bài học này bạn cần phải:
Hiểu các giải thuật sắp xếp.
Vận dụng được giải thuật để minh họa việc sắp
xếp.
Hiểu các lưu đồ của các giải thuật sắp xếp.
Hiểu các chương trình sắp xếp.
Hiểu được việc đánh giá các giải thuật.
15
Tầm quan trọng của bài toán sắp xếp
Sắp xếp một danh sách các đối tượng theo một
thứ tự nào đó là một bài toán thường được vận
dụng trong các ứng dụng tin học.
Sắp xếp là một yêu cầu không thể thiếu trong
khi thiết kế các phần mềm.
Do đó việc nghiên cứu các phương pháp sắp
xếp là rất cần thiết để vận dụng trong khi lập
trình.
16
Sắp xếp trong và sắp xếp ngoài
Sắp xếp trong là sự sắp xếp dữ liệu được tổ chức trong bộ nhớ trong
của máy tính.
Các đối tượng cần được sắp xếp là các mẩu tin gồm một hoặc nhiều
trường. Một trong các trường được gọi là khóa (key), kiểu của nó là một
kiểu có quan hệ thứ tự (như các kiểu số nguyên, số thực, chuỗi ký tự...).
Danh sách các đối tượng cần sắp xếp sẽ là một mảng của các mẩu tin
vừa nói ở trên.
Mục đích của việc sắp xếp là tổ chức lại các mẩu tin sao cho các khóa
của chúng được sắp thứ tự tương ứng với quy luật sắp xếp.
Một cách mặc nhiên, quy luật sắp xếp là thứ tự không giảm. Khi cần sắp
xếp theo thứ tự không tăng thì phải nói rõ.
Sắp xếp ngoài là sự sắp xếp được sử dụng khi số lượng đối tượng cần
sắp xếp lớn không thể lưu trữ trong bộ nhớ trong mà phải lưu trữ trên bộ
nhớ ngoài.
17
Tổ chức dữ liệu và ngôn ngữ cài đặt
Ðể trình bày các ví dụ minh họa chúng ta sẽ dùng C
(Turbo C++, Version 3.0) làm ngôn ngữ thể hiện và
sử dụng khai báo sau.
const int n = 10;
typedef int keytype;
typedef float othertype;
typedef struct recordtype {
keytype key;
othertype otherfields;
};
recordtype a[n]; /* khai bao mang a co n phan tu */
18
Tổ chức dữ liệu và ngôn ngữ cài đặt (tt)
void Swap(recordtype *x, recordtype *y)
{
recordtype temp;
temp = *x;
*x = *y;
*y = temp;
}
Cần thấy rằng thủ tục Swap lấy O(1) thời gian vì chỉ
thực hiện 3 lệnh gán nối tiếp nhau.
19
Giải thuật sắp xếp chọn (Selection Sort)
Bước 0, chọn phần tử có khóa nhỏ nhất trong n phần
tử từ a[0] đến a[n-1] và hoán vị nó với phần tử a[0].
Bước 1, chọn phần tử có khóa nhỏ nhất trong n-1 phần
tử từ a[1] đến a[n-1] và hoán vị nó với a[1].
Tổng quát ở bước thứ i, chọn phần tử có khoá nhỏ
nhất trong n-i phần tử từ a[i] đến a[n-1] và hoán vị nó
với a[i].
Sau n-1 bước này thì mảng đã được sắp xếp.
20
Phương pháp chọn phần tử
Đầu tiên ta đặt khoá nhỏ nhất là khoá của a[i] (lowkey =
a[i].key) và chỉ số của phần tử có khoá nhỏ nhất là i
(lowindex = i).
Xét các phần tử a[j] (với j từ i+1 đến n-1), nếu khoá của
a[j] nhỏ hơn khoá nhỏ nhất (a[j].key < lowkey) thì đặt lại
lại khoá nhỏ nhất là khoá của a[j] (lowkey = a[j].key) và
chỉ số của phần tử có khoá nhỏ nhất là j (lowindex = j).
Khi đã xét hết các a[j] (j>n-1) thì phần tử có khoá nhỏ
nhất là a[lowindex].
21
Ví dụ sắp xếp chọn
1210109965322Kết quả
1210Bước 8
101210Bước 7
1012109Bước 6
10910129Bước 5
109109126Bước 4
6910912105Bước 3
59109121063Bước 2
391091210652Bước 1
3910912102562Bước 0
3910912102265Ban đầu
a[9]a[8]a[7]a[6]a[5]a[4]a[3]a[2]a[1]a[0]
Khóa
Bước
22
Lưu đồ
sắp xếp chọn
Begin
i = 0
i<=n-2
lowindex = i
lowkey = a[i].key
j<=n-1
i = i+1
a[j].key<lowkey
lowindex = j
lowkey = a[j].key
j = j+1
S
j = i+1
End
swap(a[i],a[lowindex])
S
Đ
S
Đ
Đ
23
Chương trình sắp xếp chọn
void SelectionSort(void)
{ int i,j,lowindex;
keytype lowkey;
/*1*/ for (i=0; i<=n-2; i++) {
/*2*/ lowindex = i;
/*3*/ lowkey = a[i].key;
/*4*/ for (j = i+1; j <= n-1; j++)
/*5*/ if (a[j].key < lowkey) {
/*6*/ lowkey = a[j].key;
/*7*/ lowindex = j; }
/*8*/ Swap(&a[i],&a[lowindex]);
}
}
24
Đánh giá sắp xếp chọn
Hàm Swap tốn O(1).
Toàn bộ chương trình chỉ bao gồm lệnh /*1*/. Lệnh /*1*/ chứa
các lệnh “đồng cấp” /*2*/, /*3*/, /*4*/ và /*8*/, trong đó các lệnh
/*2*/, /*3*/ và /*8*/ đều tốn thời gian O(1).
Lệnh /*6*/ và /*7*/ đều tốn O(1) nên lệnh /*5*/ tốn O(1).
Vòng lặp /*4*/ thực hiện n-i-1 lần, vì j chạy từ i+1 đến n-1, mỗi
lần lấy O(1), nên lấy O(n-i-1) thời gian.
Gọi T(n) là thời gian thực hiện của chương trình, thì T(n) là thời
gian thực hiện lệnh /*1*/. Mà lệnh /*1*/ có i chạy từ 0 đến n-2
nên ta có:
)O(n
2
1)-n(n
1)-i-(nT(n) 2
2-n
0=i
25
Giải thuật sắp xếp xen (Insertion Sort)
Trước hết ta xem phần tử a[0] là một dãy đã có thứ tự.
Bước 1, xen phần tử a[1] vào danh sách đã có thứ tự
a[0] sao cho a[0], a[1] là một danh sách có thứ tự.
Bước 2, xen phần tử a[2] vào danh sách đã có thứ tự
a[0], a[1] sao cho a[0], a[1], a[2] là một danh sách có thứ
tự.
Tổng quát, bước i, xen phần tử a[i] vào danh sách đã có
thứ tự a[0], a[1], … a[i-1] sao cho a[0], a[1],.. a[i] là một
danh sách có thứ tự.
Sau n-1 bước thì kết thúc.
26
Phương pháp xen
Phần tử đang xét a[j] sẽ được xen vào vị trí thích
hợp trong danh sách các phần tử đã được sắp trước
đó a[0],a[1],..a[j-1]:
So sánh khoá của a[j] với khoá của a[j-1] đứng ngay
trước nó.
Nếu khoá của a[j] nhỏ hơn khoá của a[j-1] thì hoán
đổi a[j-1] và a[j] cho nhau và tiếp tục so sánh khoá
của a[j-1] (lúc này a[j-1] chứa nội dung của a[j]) với
khoá của a[j-2] đứng ngay trước nó...
27
Ví dụ sắp xếp xen
1210109965322Bước 9
121010996522Bước 8
12101096522Bước 7
121096522Bước 6
12106522Bước 5
106522Bước 4
6522Bước 3
652Bước 2
65Bước 1
3910912102265Ban đầu
a[9]a[8]A[7]a[6]a[5]a[4]a[3]a[2]a[1]a[0]Khóa
Bước
28
Lưu đồ
sắp xếp xen
Begin
i = 1
i<=n-1
(j>0) and
(a[j].key < a[j-1].key)
i = i+1
j = i
End
swap(a[j],a[j-1])
j = j-1
S
Đ
Đ
S
29
Chương trình sắp xếp xen
void InsertionSort(void)
{
int i,j;
/*1*/ for (i = 1; i<= n-1; i++) {
/*2*/ j = i;
/*3*/ while ((j>0) && (a[j].key < a[j-1].key)) {
/*4*/ Swap(&a[j], &a[j-1]);
/*5*/ j= j-1;
}
}
}
30
Đánh giá sắp xếp xen
Các lệnh /*4*/ và /*5*/ đều lấy O(1). Vòng lặp
/*3*/, trong trường hợp xấu nhất, chạy i lần (j
giảm từ i đến 1), mỗi lần tốn O(1) nên /*3*/ lấy i
thời gian.
Lệnh /*2*/ và /*3*/ là hai lệnh nối tiếp nhau, lệnh
/*2*/ lấy O(1) nên cả hai lệnh này lấy i.
Vòng lặp /*1*/ có i chạy từ 1 đến n-1 nên ta có:
)O(n
2
1)-n(n
iT(n) 2
1-n
1i
31
Giải thuật sắp xếp “nổi bọt” (Bubble Sort)
Bước 1: Xét các phần tử a[j] (j giảm từ n-1 đến 1), so
sánh khoá của a[j] với khoá của a[j-1]. Nếu khoá của
a[j] nhỏ hơn khoá của a[j-1] thì hoán đổi a[j] và a[j-1]
cho nhau. Sau bước này thì a[0] có khoá nhỏ nhất.
Bước 2: Xét các phần tử a[j] (j giảm từ n-1 đến 2), so
sánh khoá của a[j] với khoá của a[j-1]. Nếu khoá của
a[j] nhỏ hơn khoá của a[j-1] thì hoán đổi a[j] và a[j-1]
cho nhau. Sau bước này thì a[1] có khoá nhỏ thứ 2.
…
Sau n-1 bước thì kết thúc.
32
Ví dụ sắp xếp “nổi bọt”
1210109965322Kết quả
1210Bước 9
121010Bước 8
1210109Bước 7
12101099Bước 6
121010996Bước 5
1210109965Bước 4
10121099653Bước 3
109121093652Bước 2
9109121032652Bước 1
3910912102265Ban đầu
a[9]a[8]a[7]a[6]A[5]a[4]a[3]a[2]a[1]a[0]
Khóa
Bước
33
Lưu đồ
sắp xếp nổi bọt
Begin
i = 0
i<=n-2
i = i+1
j = n-1
End
swap(a[j],a[j-1])
S
Đ
Đ S
a[j].key < a[j-1].key
j>= i+1
Đ
j = j-1
S
34
Chương trình
sắp xếp “nổi bọt”
void BubbleSort(void)
{ int i,j;
/*1*/ for(i= 0; i<= n-2; i++)
/*2*/ for(j=n-1;j>=i+1; j--)
/*3*/ if (a[j].key < a[j-1].key)
/*4*/ Swap(&a[j],&a[j-1]);
}
Begin
i = 0
i<=n-2
i = i+1
j = n-1
End
swap(a[j],a[j-1])
S
Đ
Đ S
a[j].key < a[j-1].key
j>=
i+1
Đ
j = j-1
S
35
Ý tưởng của QuickSort
Chọn một giá trị khóa v làm chốt (pivot).
Phân hoạch dãy a[0]..a[n-1] thành hai mảng con "bên trái" và
"bên phải". Mảng con "bên trái" bao gồm các phần tử có khóa
nhỏ hơn chốt, mảng con "bên phải" bao gồm các phần tử có
khóa lớn hơn hoặc bằng chốt.
Sắp xếp mảng con “bên trái” và mảng con “bên phải”.
Sau khi đã sắp xếp được mảng con “bên trái” và mảng con
“bên phải” thì mảng đã cho sẽ được sắp bởi vì tất cả các khóa
trong mảng con “bên trái” đều nhỏ hơn các khóa trong mảng
con “bên phải”.
Việc sắp xếp các mảng con “bên trái” và “bên phải” cũng được
tiến hành bằng phương pháp nói trên.
Một mảng chỉ gồm một phần tử hoặc gồm nhiều phần tử có
khóa bằng nhau thì đã có thứ tự.
36
Phương pháp chọn chốt
Chọn giá trị khóa lớn nhất trong hai phần tử có khóa
khác nhau đầu tiên kể từ trái qua.
Nếu mảng chỉ gồm một phần tử hay gồm nhiều phần tử
có khóa bằng nhau thì không có chốt.
Ví dụ: Chọn chốt trong các mảng sau
– Cho mảng gồm các phần tử có khoá là 6, 6, 5, 8, 7, 4, ta chọn
chốt là 6 (khoá của phần tử đầu tiên).
– Cho mảng gồm các phần tử có khoá là 6, 6, 7, 5, 7, 4, ta chọn
chốt là 7 (khoá của phần tử thứ 3).
– Cho mảng gồm các phần tử có khoá là 6, 6, 6, 6, 6, 6 thì không
có chốt (các phần tử có khoá bằng nhau).
– Cho mảng gồm một phần tử có khoá là 6 thì không có chốt (do
chỉ có một phần tử).
37
Phương pháp phân hoạch
Ðể phân hoạch mảng ta dùng 2 "con nháy" L và R trong đó
L từ bên trái và R từ bên phải.
Ta cho L chạy sang phải cho tới khi gặp phần tử có khóa ≥
chốt
Cho R chạy sang trái cho tới khi gặp phần tử có khóa <
chốt.
Tại chỗ dừng của L và R nếu L < R thì hoán vị a[L],a[R].
Lặp lại quá trình dịch sang phải, sang trái của 2 "con nháy"
L và R cho đến khi L > R.
Khi đó L sẽ là điểm phân hoạch, cụ thể là a[L] là phần tử
đầu tiên của mảng con “bên phải”.
38
Ví dụ về phân hoạch
4151812510285Khoá
9876543210Chỉ số
Chốt p = 8
L=0 R=9
39
Ví dụ về phân hoạch
4151812510285Khoá
9876543210Chỉ số
L=1
Chốt p = 8
R=9
40
Ví dụ về phân hoạch
8151812510245Khoá
9876543210Chỉ số
L=1
Chốt p = 8
R=9
41
Ví dụ về phân hoạch
8151812510245Khoá
9876543210Chỉ số
L=2
Chốt p = 8
R=9
42
Ví dụ về phân hoạch
8151812510245Khoá
9876543210Chỉ số
L=3
Chốt p = 8
R=9
43
Ví dụ về phân hoạch
8151812510245Khoá
9876543210Chỉ số
L=3
Chốt p = 8
R=8
44
Ví dụ về phân hoạch
8151812510245Khoá
9876543210Chỉ số
L=3
Chốt p = 8
R=7
45
Ví dụ về phân hoạch
8151081251245Khoá
9876543210Chỉ số
L=3
Chốt p = 8
R=7
46
Ví dụ về phân hoạch
8151081251245Khoá
9876543210Chỉ số
L=4
Chốt p = 8
R=7
47
Ví dụ về phân hoạch
8151081251245Khoá
9876543210Chỉ số
L=5
Chốt p = 8
R=7
48
Ví dụ về phân hoạch
8151081251245Khoá
9876543210Chỉ số
L=5
Chốt p = 8
R=6
49
Ví dụ về phân hoạch
8151081251245Khoá
9876543210Chỉ số
L=5
Chốt p = 8
R=5
50
Ví dụ về phân hoạch
8151081251245Khoá
9876543210Chỉ số
L=5
Chốt p = 8
R=4
51245
43210
81510812
98765
51
Giải thuật QuickSort
Ðể sắp xếp mảng a[i]..a[j] ta làm các bước sau:
– Xác định chốt.
– Phân hoạch mảng đã cho thành hai mảng con
a[i]..a[k-1] và a[k]..a[j].
– Sắp xếp mảng a[i]..a[k-1] (Ðệ quy).
– Sắp xếp mảng a[k]..a[j] (Ðệ quy).
Đệ quy sẽ dừng khi không còn tìm thấy chốt.
52
Ví dụ về QuickSort
Chốt p = 8
51245 81510812
Chốt p = 5
4151812510285Khoá
9876543210Chỉ số
53
Ví dụ về QuickSort
8151081251245Khoá
9876543210Chỉ số
Chốt p = 8
51
5
245
1
81510812
Chốt p = 5
241 55
Chốt p = 4
54
Ví dụ về QuickSort
8151081251245Khoá
9876543210Chỉ số
Chốt p = 8
51
5
245
1
81510812
Chốt p = 5
2
4
4
2
1 55
Chốt p = 4
21 4
Chốt p = 2
1 2
xong xong
xong
xong
Chốt p = 12
55
Ví dụ về QuickSort
8151081251245Khoá
9876543210Chỉ số
Chốt p = 8
51
5
245
1
8
12
1510812
8
Chốt p = 5
2
4
4
2
1 55
Chốt p = 4
21 4
Chốt p = 2
1 2
xong xong
xong
xong
Chốt p = 12
1088 1215
Chốt p = 10
88 10
xong xong
Chốt p = 15
56
Ví dụ về QuickSort
8151081251245Khoá
9876543210Chỉ số
Chốt p = 8
51
5
245
1
8
12
1510812
8
Chốt p = 5
2
4
4
2
1 55
Chốt p = 4
21 4
Chốt p = 2
1 2
xong xong
xong
xong
Chốt p = 12
1088 12
15
15
12
Chốt p = 10
88 10
xong xong
Chốt p = 15
12 15
xong xong
57
Lưu đồ
hàm FindPivot
Begin
k = i+1
firstkey = a[i].key
(k<=j) and
(a[k].key == firstkey
k > j
a[k].key>firstkey
k = k+1
End
Đ
Đ
Đ
S
S
return -1
return i return k
i, j
S
58
Chương trình
hàm FindPivot
int FindPivot(int i,int j)
{ keytype firstkey;
int k ;
k = i+1;
firstkey = a[i].key;
while ( (k <= j) && (a[k].key ==
firstkey) ) k++;
if (k > j) return -1;
else
if (a[k].key>firstkey) return k;
else return i;
}
Begin
k = i+1
firstkey = a[i].key
(k<=j) and
(a[k].key == firstkey
k > j
a[k].key>firstkey
k = k+1
End
Đ
Đ
Đ
S
S
return -1
return i return k
i, j
S
59
Phân tích hàm FindPivot
int FindPivot(int i,int j)
{ keytype firstkey;
int k ;
/*1*/ k = i+1;
/*2*/ firstkey = a[i].key;
/*3*/ while ( (k <= j) && (a[k].key == firstkey) ) k++;
/*4*/ if (k > j) return -1;
else
/*5*/ if (a[k].key>firstkey) return k; else return i;
}
/*1*/, /*2*/, /*3*/ và
/*4*/ nối tiếp nhau.
Lệnh WHILE là tốn
nhiều thời gian nhất.
Trong trường hợp xấu
nhất thì k chạy từ i+1
đến j, tức là vòng lặp
thực hiện j-i lần, mỗi
lần O(1) do đó tốn j-i
Đặc biệt khi i=0 và j=n-
1, thì thời gian thực
hiện là n-1 hay T(n) =
O(n).
60
Lưu đồ
hàm Partition
Begin
L = i; R = j
L <= R
a[R].key >= pivot
a[L].key < pivot
L = L+1
End
Đ
ĐS
S
return L
i, j, pivot
S
R = R-1L < R
Swap(a[L], a[R])
Đ
S
Đ
61
Hàm
Partition
int Partition(int i,int j, keytype pivot)
{ int L,R;
/*1*/ L = i;
/*2*/ R = j;
/*3*/ while (L <= R) {
/*4*/ while (a[L].key < pivot) L++;
/*5*/ while (a[R].key >= pivot) R--;
/*6*/ if (L<R) Swap(&a[L],&a[R]);
}
/*7*/ return L; /*Tra ve diem phan
hoach*/
}
Begin
L = i; R = j
L <= R
a[R].key >= pivot
a[L].key < pivot
L = L+1
End
Đ
ĐS
S
return L
i, j, pivot
S
R = R-1L < R
Swap(a[L], a[R])
Đ
S
Đ
62
Phân tích hàm Partition
int Partition(int i,int j, keytype pivot)
{ int L,R;
/*1*/ L = i;
/*2*/ R = j;
/*3*/ while (L <= R) {
/*4*/ while (a[L].key < pivot) L++;
/*5*/ while (a[R].key >= pivot) R--;
/*6*/ if (L<R) Swap(&a[L],&a[R]);
}
/*7*/ return L;
}
/*1*/, /*2*/, /*3*/ và /*7*/ nối tiếp nhau
Thời gian thực hiện của /*3*/ là lớn nhất.
Các lệnh /*4*/, /*5*/ và /*6*/ là thân của lệnh
/*3*/, trong đó lệnh /*6*/ lấy O(1).
Lệnh /*4*/ và lệnh /*5*/ thực hiện việc di
chuyển L sang phải và R sang trái cho đến
khi L và R gặp nhau, thực chất là duyệt các
phần tử mảng, mỗi phần tử một lần, mỗi lần
tốn O(1) thời gian. Tổng cộng việc duyệt này
tốn j-i thời gian.
Vòng lặp /*3*/ thực chất là để xét xem khi
nào thì duyệt xong, do đó thời gian thực hiện
của lệnh /*3*/ chính là thời gian thực hiện
của hai lệnh /*4*/ và /*5*/ và do đó là j-i.
Đặc biệt khi i=0 và j=n-1 ta có T(n) = O(n).
63
Hàm QuickSort
void QuickSort(int i,int j)
{ keytype pivot;
int pivotindex, k;
pivotindex = FindPivot(i,j);
if (pivotindex != -1) {
pivot = a[pivotindex].key;
k = Partition(i,j,pivot);
QuickSort(i,k-1);
QuickSort(k,j);
}
}
64
Đánh giá QuickSort
(Trường hợp xấu nhất)
Giả sử các giá trị khóa của mảng khác nhau nên hàm FindPivot luôn
tìm được chốt và đệ quy chỉ dừng khi kích thước bài toán bằng 1.
Gọi T(n) là thời gian thức hiện việc QuickSort mảng có n phần tử.
Thời gian tìm chốt và phân hoạch mảng là O(n) = n.
Khi n = 1, thủ tục QuickSort chỉ làm một nhiệm vụ duy nhất là gọi hàm
Findpivot với kích thước bằng 1, hàm này tốn thời gian O(1) =1.
Trong trường hợp xấu nhất, phân hoạch lệch.
Khi đó ta có thể thành lập phương trình đệ quy như sau:
1>nnêun+T(1)+1)-T(n
1=nnêu1
T(n)
Giải PT này ta được T(n) =O(n2)
65
Đánh giá QuickSort
(Trường hợp tốt nhất)
Trong trường hợp tốt nhất khi ta chọn được
chốt sao cho hai mảng con có kích thước
bằng nhau và bằng n/2.
Lúc đó ta có phương trình đệ quy như sau:
Giải PT này ta được T(n) =O(nlogn)
1nnêun)
2
n
2T(
1nnêu1
T(n)
66
HeapSort: Ðịnh nghĩa Heap
Cây sắp thứ tự bộ phận hay còn gọi là heap
là cây nhị phân mà giá trị tại mỗi nút (khác
nút lá) đều không lớn hơn giá trị của các con
của nó.
Ta có nhận xét rằng nút gốc của cây sắp thứ
tự bộ phận có giá trị nhỏ nhất.
67
Ví dụ về heap
2
3
6
5 9 6 7
7
6 9
68
HeapSort : Ý tưởng giải thuật
(1) Xem mảng ban đầu là một cây nhị phân. Mỗi nút trên cây lưu trữ
một phần tử mảng, trong đó a[0] là nút gốc và mỗi nút không là nút lá
a[i] có con trái là a[2i+1] và con phải là a[2i+2]. Với cách tổ chức này
thì cây nhị phân thu được sẽ có các nút trong là các nút a[0], …, a[(n-
2)/2]. Tất cả các nút trong đều có 2 con, ngoại trừ nút a[(n-2)/2] có thể
chỉ có một con trái (trong trường hợp n là một số chẵn).
(2) Sắp xếp cây ban đầu thành một heap căn cứ vào giá trị khoá của
các nút.
(3) Hoán đổi nút gốc a[0] cho cho nút lá cuối cùng.
(4) Sắp lại cây sau khi đã bỏ đi nút lá cuối cùng để nó trở thành một
heap mới.
Lặp lại quá trình (3) và (4) cho tới khi cây chỉ còn một nút. Nút này
cùng với các nút lá đã bỏ đi tạo thành một mảng sắp theo thứ tự giảm.
69
Thiết kế hàm PushDown
PushDown nhận vào 2 tham số first và last để đẩy nút first xuống.
Giả sử a[first],..,a[last] đã đúng vị trí của một heap, ngoại trừ a[first].
PushDown dùng để đẩy phần tử a[first] xuống đúng vị trí của nó trong cây.
Xét a[first], có các khả năng có thể xẩy ra:
– Nếu a[first] chỉ có một con trái và nếu khoá của nó lớn hơn khoá của con trái
(a[first].key > a[2*first+1].key) thì hoán đổi a[first] cho con trái của nó và kết
thúc.
– Nếu a[first] có khoá lớn hơn con trái của nó và khoá của con trái không lớn
hơn khoá của con phải thì hoán đổi a[first] cho con trái của nó, việc này có thể
gây ra tình trạng con trái sẽ không đúng vị trí nên phải xem xét lại con trái để
có thể đẩy xuống.
– Ngược lại, nếu a[first] có khoá lớn hơn khoá của con phải của nó và khoá của
con phải nhỏ hơn khoá của con trái thì hoán đổi a[first] cho con phải của nó,
việc này có thể gây ra tình trạng con phải sẽ không đúng vị trí nên phải tiếp
tục xem xét con phải để có thể đẩy xuống.
– Nếu tất cả các trường hợp trên đều không xẩy ra thì a[first] đã đúng vị trí.
70
Lưu đồ
hàm PushDown
Begin
r = first
r <= (last-1)/2
a[r].key > a[last].key
last==2*r+1
r = last
End
Đ
Đ S
S
first, last
S
swap(a[r],a[last])
a[r].key > a[2*r+1].key
and
a[2*r+1].key <= a[2*r+2].key
swap(a[r], a[2*r+1])
r = 2*r+1
Đ
S
Đ
S
a[r].key > a[2*r+2].key
and
a[2*r+2].key < a[2*r+1].key
swap(a[r], a[2*r+2])
r = 2*r+2
Đ
r = last
71
Chương trình hàm Pushdown
void PushDown(int first,int last)
{ int r;
r= first;
while (r <= (last-1)/2)
if (last == 2*r+1) {
if (a[r].key > a[last].key) Swap(&a[r],&a[last]);
r = last;
} else
if ((a[r].key>a[2*r+1].key) && (a[2*r+1].key<=a[2*r+2].key))
{
Swap(&a[r],&a[2*r+1]);
r = 2*r+1 ;
} else
if ((a[r].key>a[2*r+2].key) && (a[2*r+2].key<a[2*r+1].key))
{
Swap(&a[r],&a[2*r+2]);
r = 2*r+2 ;
}
else
r = last;
}
72
Phân tích hàm PushDown
Ta xét PushDown(0,n-1), tức là PushDown trên cây có n nút.
PushDown chỉ duyệt trên một nhánh nào đó của cây nhị phân,
tức là sau mỗi lần lặp thì số nút còn lại một nửa. Một cách cụ
thể, trước hết PushDown trên cây có n nút; Sau lần lặp thứ
nhất, PushDown trên cây có n/2 nút; Sau lần lặp thứ hai,
PushDown trên cây có n/4 nút;… Tổng quát, Sau lần lặp thứ i,
PushDown trên cây có n/2i nút.
Như vậy, trong trường hợp xấu nhất (luôn phải thực hiện việc
đẩy xuống) thì lệnh lặp while phải thực hiện i lần sao chon/2i =
1 tức là i=logn (i=logn là số lần lặp của lệnh while, trong trường
hợp xấu nhất). Mà mỗi lần lặp chỉ thực hiện một lệnh IF với
thân lệnh IF là lời gọi Swap và lệnh gán, do đó tốn O(1) = 1
đơn vị thời gian.
Từ đó ta thấy PushDown lấy O(logn) để đẩy xuống một nút
trong cây có n nút.
73
Chương trình hàm HeapSort
void HeapSort(void)
{ int i;
/*1*/ for(i = (n-2)/2; i>=0; i--)
/*2*/ PushDown(i,n-1);
/*3*/ for(i = n-1; i>=2; i--) {
/*4*/ Swap(&a[0],&a[i]);
/*5*/ PushDown(0,i-1);
}
/*6*/ Swap(&a[0],&a[1]);
}
74
Phân tích HeapSort
Hàm PushDown lấy O(logn).
Trong HeapSort,
– Vòng lặp /*1*/-/*2*/ lặp (n-2)/2+1 lần mà mỗi lần lấy
O(logn) nên thời gian thực hiện /*1*/-/*2*/ là O(n
logn).
– Vòng lặp /*3*/-/*5*/ lặp n-2 lần, mỗi lần lấy O(logn)
nên thời gian thực hiện của /*3*/-/*5*/ là O(n logn).
Thời gian thực hiện HeapSort là O(nlogn).
75
HeapSort: Trình bày bằng bảng
Tạo Heap
3910912102265Ban đầu
a[9]a[8]a[7]a[6]A[5]a[4]a[3]a[2]a[1]a[0]
Khóa
Bước
76
77
78
79
80
81

More Related Content

What's hot

Sap xep va tim kiem
Sap xep va tim kiem Sap xep va tim kiem
Sap xep va tim kiem acumenvn
 
Giáo trình Phân tích và thiết kế giải thuật - CHAP 1
Giáo trình Phân tích và thiết kế giải thuật - CHAP 1Giáo trình Phân tích và thiết kế giải thuật - CHAP 1
Giáo trình Phân tích và thiết kế giải thuật - CHAP 1Nguyễn Công Hoàng
 
Bài tập CTDL và GT 1
Bài tập CTDL và GT 1Bài tập CTDL và GT 1
Bài tập CTDL và GT 1Hồ Lợi
 
Giáo trình Phân tích và thiết kế giải thuật - CHAP 4
Giáo trình Phân tích và thiết kế giải thuật - CHAP 4Giáo trình Phân tích và thiết kế giải thuật - CHAP 4
Giáo trình Phân tích và thiết kế giải thuật - CHAP 4Nguyễn Công Hoàng
 
Ctdl+va+gt chuong+1 4
Ctdl+va+gt chuong+1 4Ctdl+va+gt chuong+1 4
Ctdl+va+gt chuong+1 4Do Ngoc Tuan
 
Phân tích một số thuật toán
Phân tích một số thuật toánPhân tích một số thuật toán
Phân tích một số thuật toánHồ Lợi
 
TÌM HIỂU VỀ MỘT SỐ THUẬT TOÁN SẮP XẾP ĐƠN GIẢN
TÌM HIỂU VỀ MỘT SỐ THUẬT TOÁN SẮP XẾP ĐƠN GIẢNTÌM HIỂU VỀ MỘT SỐ THUẬT TOÁN SẮP XẾP ĐƠN GIẢN
TÌM HIỂU VỀ MỘT SỐ THUẬT TOÁN SẮP XẾP ĐƠN GIẢNTrần Nguyên
 
MATMA - Chuong3 l tso
MATMA - Chuong3 l tsoMATMA - Chuong3 l tso
MATMA - Chuong3 l tsoSai Lemovom
 
Giáo trình Phân tích và thiết kế giải thuật - CHAP 3
Giáo trình Phân tích và thiết kế giải thuật - CHAP 3Giáo trình Phân tích và thiết kế giải thuật - CHAP 3
Giáo trình Phân tích và thiết kế giải thuật - CHAP 3Nguyễn Công Hoàng
 
Chuong 2. de quy dai hoc
Chuong 2. de quy   dai hocChuong 2. de quy   dai hoc
Chuong 2. de quy dai hocVũ Nam
 
Phân tích và thiết kế thuật toán độ phức tạp
Phân tích và thiết kế thuật toán   độ phức tạpPhân tích và thiết kế thuật toán   độ phức tạp
Phân tích và thiết kế thuật toán độ phức tạpgiangnguyn853776
 
Bài 1: Tổng quan về cấu trúc và giải thuật - Giáo trình FPT
Bài 1: Tổng quan về cấu trúc và giải thuật - Giáo trình FPTBài 1: Tổng quan về cấu trúc và giải thuật - Giáo trình FPT
Bài 1: Tổng quan về cấu trúc và giải thuật - Giáo trình FPTMasterCode.vn
 
Giáo trình Phân tích và thiết kế giải thuật - CHAP 6
Giáo trình Phân tích và thiết kế giải thuật - CHAP 6Giáo trình Phân tích và thiết kế giải thuật - CHAP 6
Giáo trình Phân tích và thiết kế giải thuật - CHAP 6Nguyễn Công Hoàng
 
Chuong 2 co so phan tich do phuc tap cua giai thuat - sinh vien 2
Chuong 2   co so phan tich do phuc tap cua giai thuat - sinh vien 2Chuong 2   co so phan tich do phuc tap cua giai thuat - sinh vien 2
Chuong 2 co so phan tich do phuc tap cua giai thuat - sinh vien 2Hồ Lợi
 

What's hot (19)

Sap xep va tim kiem
Sap xep va tim kiem Sap xep va tim kiem
Sap xep va tim kiem
 
Giáo trình Phân tích và thiết kế giải thuật - CHAP 1
Giáo trình Phân tích và thiết kế giải thuật - CHAP 1Giáo trình Phân tích và thiết kế giải thuật - CHAP 1
Giáo trình Phân tích và thiết kế giải thuật - CHAP 1
 
Bài tập CTDL và GT 1
Bài tập CTDL và GT 1Bài tập CTDL và GT 1
Bài tập CTDL và GT 1
 
Hệ mật mã Elgamal
Hệ mật mã ElgamalHệ mật mã Elgamal
Hệ mật mã Elgamal
 
Giáo trình Phân tích và thiết kế giải thuật - CHAP 4
Giáo trình Phân tích và thiết kế giải thuật - CHAP 4Giáo trình Phân tích và thiết kế giải thuật - CHAP 4
Giáo trình Phân tích và thiết kế giải thuật - CHAP 4
 
Ctdl+va+gt chuong+1 4
Ctdl+va+gt chuong+1 4Ctdl+va+gt chuong+1 4
Ctdl+va+gt chuong+1 4
 
Phân tích một số thuật toán
Phân tích một số thuật toánPhân tích một số thuật toán
Phân tích một số thuật toán
 
TÌM HIỂU VỀ MỘT SỐ THUẬT TOÁN SẮP XẾP ĐƠN GIẢN
TÌM HIỂU VỀ MỘT SỐ THUẬT TOÁN SẮP XẾP ĐƠN GIẢNTÌM HIỂU VỀ MỘT SỐ THUẬT TOÁN SẮP XẾP ĐƠN GIẢN
TÌM HIỂU VỀ MỘT SỐ THUẬT TOÁN SẮP XẾP ĐƠN GIẢN
 
MATMA - Chuong3 l tso
MATMA - Chuong3 l tsoMATMA - Chuong3 l tso
MATMA - Chuong3 l tso
 
MATMAT- Chuong1
MATMAT- Chuong1MATMAT- Chuong1
MATMAT- Chuong1
 
Chuong 1
Chuong 1Chuong 1
Chuong 1
 
Giáo trình Phân tích và thiết kế giải thuật - CHAP 3
Giáo trình Phân tích và thiết kế giải thuật - CHAP 3Giáo trình Phân tích và thiết kế giải thuật - CHAP 3
Giáo trình Phân tích và thiết kế giải thuật - CHAP 3
 
Chuong 2. de quy dai hoc
Chuong 2. de quy   dai hocChuong 2. de quy   dai hoc
Chuong 2. de quy dai hoc
 
Phân tích và thiết kế thuật toán độ phức tạp
Phân tích và thiết kế thuật toán   độ phức tạpPhân tích và thiết kế thuật toán   độ phức tạp
Phân tích và thiết kế thuật toán độ phức tạp
 
Bài 1: Tổng quan về cấu trúc và giải thuật - Giáo trình FPT
Bài 1: Tổng quan về cấu trúc và giải thuật - Giáo trình FPTBài 1: Tổng quan về cấu trúc và giải thuật - Giáo trình FPT
Bài 1: Tổng quan về cấu trúc và giải thuật - Giáo trình FPT
 
Giáo trình Phân tích và thiết kế giải thuật - CHAP 6
Giáo trình Phân tích và thiết kế giải thuật - CHAP 6Giáo trình Phân tích và thiết kế giải thuật - CHAP 6
Giáo trình Phân tích và thiết kế giải thuật - CHAP 6
 
Chuong 2 co so phan tich do phuc tap cua giai thuat - sinh vien 2
Chuong 2   co so phan tich do phuc tap cua giai thuat - sinh vien 2Chuong 2   co so phan tich do phuc tap cua giai thuat - sinh vien 2
Chuong 2 co so phan tich do phuc tap cua giai thuat - sinh vien 2
 
Hệ mật mã elgamal
Hệ mật mã elgamalHệ mật mã elgamal
Hệ mật mã elgamal
 
Đề tài: Xây dựng bài thí nghiệm xử lý tín hiệu số trên Matlab
Đề tài: Xây dựng bài thí nghiệm xử lý tín hiệu số trên MatlabĐề tài: Xây dựng bài thí nghiệm xử lý tín hiệu số trên Matlab
Đề tài: Xây dựng bài thí nghiệm xử lý tín hiệu số trên Matlab
 

Viewers also liked

Bai8 caynhiphan
Bai8 caynhiphanBai8 caynhiphan
Bai8 caynhiphanHồ Lợi
 
Bai5 dsachlket
Bai5 dsachlketBai5 dsachlket
Bai5 dsachlketHồ Lợi
 
Ppresentacion eu
Ppresentacion euPpresentacion eu
Ppresentacion eupak70
 
Bai7 timkiemnhiphan
Bai7 timkiemnhiphanBai7 timkiemnhiphan
Bai7 timkiemnhiphanHồ Lợi
 
Bai2 ptthuatgiai
Bai2 ptthuatgiaiBai2 ptthuatgiai
Bai2 ptthuatgiaiHồ Lợi
 
Catálogo de Produtos Star Life
Catálogo de Produtos Star LifeCatálogo de Produtos Star Life
Catálogo de Produtos Star LifeMurilo Alves
 
Dynamic Balance Concept
Dynamic Balance ConceptDynamic Balance Concept
Dynamic Balance ConceptRon Batdorf
 
Focus group summary of final product
Focus group summary of final productFocus group summary of final product
Focus group summary of final productlilywilkinson
 
Si planificacion 2015 ...
Si  planificacion 2015  ...Si  planificacion 2015  ...
Si planificacion 2015 ...profesoraudp
 

Viewers also liked (11)

Bai4 binsort
Bai4 binsortBai4 binsort
Bai4 binsort
 
Bai8 caynhiphan
Bai8 caynhiphanBai8 caynhiphan
Bai8 caynhiphan
 
Bai5 dsachlket
Bai5 dsachlketBai5 dsachlket
Bai5 dsachlket
 
Ppresentacion eu
Ppresentacion euPpresentacion eu
Ppresentacion eu
 
Bai7 timkiemnhiphan
Bai7 timkiemnhiphanBai7 timkiemnhiphan
Bai7 timkiemnhiphan
 
Bai6 stacks
Bai6 stacksBai6 stacks
Bai6 stacks
 
Bai2 ptthuatgiai
Bai2 ptthuatgiaiBai2 ptthuatgiai
Bai2 ptthuatgiai
 
Catálogo de Produtos Star Life
Catálogo de Produtos Star LifeCatálogo de Produtos Star Life
Catálogo de Produtos Star Life
 
Dynamic Balance Concept
Dynamic Balance ConceptDynamic Balance Concept
Dynamic Balance Concept
 
Focus group summary of final product
Focus group summary of final productFocus group summary of final product
Focus group summary of final product
 
Si planificacion 2015 ...
Si  planificacion 2015  ...Si  planificacion 2015  ...
Si planificacion 2015 ...
 

Similar to Bai3 timkiem sapxep

Chuong 2 Tim Kiem N Sap Xep
Chuong 2   Tim Kiem N Sap XepChuong 2   Tim Kiem N Sap Xep
Chuong 2 Tim Kiem N Sap Xepquang
 
Chap1 new (tran dai's conflicted copy 2013 04-02)
Chap1 new (tran dai's conflicted copy 2013 04-02)Chap1 new (tran dai's conflicted copy 2013 04-02)
Chap1 new (tran dai's conflicted copy 2013 04-02)Loc Tran
 
Ctdl+va+gt chuong+1 4
Ctdl+va+gt chuong+1 4Ctdl+va+gt chuong+1 4
Ctdl+va+gt chuong+1 4Do Ngoc Tuan
 
Bài tập CTDL và GT 12
Bài tập CTDL và GT 12Bài tập CTDL và GT 12
Bài tập CTDL và GT 12Hồ Lợi
 
5 Array
5 Array5 Array
5 ArrayCuong
 
Tuan1_GioiThieu.pdf
Tuan1_GioiThieu.pdfTuan1_GioiThieu.pdf
Tuan1_GioiThieu.pdfNguynVnTun74
 
Tai lieu boi duong doi tuyen quoc gia 2013 3
Tai lieu boi duong doi tuyen quoc gia 2013 3Tai lieu boi duong doi tuyen quoc gia 2013 3
Tai lieu boi duong doi tuyen quoc gia 2013 3nataliej4
 
Ctdl lab07-cac thuat-toan_sap_xep
Ctdl lab07-cac thuat-toan_sap_xepCtdl lab07-cac thuat-toan_sap_xep
Ctdl lab07-cac thuat-toan_sap_xepNguyễn Ngọc Hà
 
304686218-Chia-đoi-tập-vdgdhợp-2.docx
304686218-Chia-đoi-tập-vdgdhợp-2.docx304686218-Chia-đoi-tập-vdgdhợp-2.docx
304686218-Chia-đoi-tập-vdgdhợp-2.docxNguynAnThch
 
Tìm kiếm và sắp nội
Tìm kiếm và sắp nộiTìm kiếm và sắp nội
Tìm kiếm và sắp nộikikihoho
 
1. Algorithms_ Giải thuật.ppt
1. Algorithms_ Giải thuật.ppt1. Algorithms_ Giải thuật.ppt
1. Algorithms_ Giải thuật.pptNynonBi
 
Lớp 11 --chương 4 -- bài 11 --Kiểu mảng
Lớp 11 --chương 4 -- bài 11 --Kiểu mảngLớp 11 --chương 4 -- bài 11 --Kiểu mảng
Lớp 11 --chương 4 -- bài 11 --Kiểu mảngHoàng Kỳ Anh
 

Similar to Bai3 timkiem sapxep (20)

CHƯƠNG 4.pdf
CHƯƠNG 4.pdfCHƯƠNG 4.pdf
CHƯƠNG 4.pdf
 
Chuong 2 Tim Kiem N Sap Xep
Chuong 2   Tim Kiem N Sap XepChuong 2   Tim Kiem N Sap Xep
Chuong 2 Tim Kiem N Sap Xep
 
Thuat Toan
Thuat ToanThuat Toan
Thuat Toan
 
Thuat Toan 2
Thuat Toan 2Thuat Toan 2
Thuat Toan 2
 
Chap1 new (tran dai's conflicted copy 2013 04-02)
Chap1 new (tran dai's conflicted copy 2013 04-02)Chap1 new (tran dai's conflicted copy 2013 04-02)
Chap1 new (tran dai's conflicted copy 2013 04-02)
 
Ctdl+va+gt chuong+1 4
Ctdl+va+gt chuong+1 4Ctdl+va+gt chuong+1 4
Ctdl+va+gt chuong+1 4
 
CHƯƠNG 2.pdf
CHƯƠNG 2.pdfCHƯƠNG 2.pdf
CHƯƠNG 2.pdf
 
Bài tập CTDL và GT 12
Bài tập CTDL và GT 12Bài tập CTDL và GT 12
Bài tập CTDL và GT 12
 
5 Array
5 Array5 Array
5 Array
 
Gt de quy
Gt de quyGt de quy
Gt de quy
 
Gt de quy_2
Gt de quy_2Gt de quy_2
Gt de quy_2
 
Tuan1_GioiThieu.pdf
Tuan1_GioiThieu.pdfTuan1_GioiThieu.pdf
Tuan1_GioiThieu.pdf
 
Olympiad help
Olympiad helpOlympiad help
Olympiad help
 
Tai lieu boi duong doi tuyen quoc gia 2013 3
Tai lieu boi duong doi tuyen quoc gia 2013 3Tai lieu boi duong doi tuyen quoc gia 2013 3
Tai lieu boi duong doi tuyen quoc gia 2013 3
 
Ctdl lab07-cac thuat-toan_sap_xep
Ctdl lab07-cac thuat-toan_sap_xepCtdl lab07-cac thuat-toan_sap_xep
Ctdl lab07-cac thuat-toan_sap_xep
 
304686218-Chia-đoi-tập-vdgdhợp-2.docx
304686218-Chia-đoi-tập-vdgdhợp-2.docx304686218-Chia-đoi-tập-vdgdhợp-2.docx
304686218-Chia-đoi-tập-vdgdhợp-2.docx
 
Pt04 de qui
Pt04 de quiPt04 de qui
Pt04 de qui
 
Tìm kiếm và sắp nội
Tìm kiếm và sắp nộiTìm kiếm và sắp nội
Tìm kiếm và sắp nội
 
1. Algorithms_ Giải thuật.ppt
1. Algorithms_ Giải thuật.ppt1. Algorithms_ Giải thuật.ppt
1. Algorithms_ Giải thuật.ppt
 
Lớp 11 --chương 4 -- bài 11 --Kiểu mảng
Lớp 11 --chương 4 -- bài 11 --Kiểu mảngLớp 11 --chương 4 -- bài 11 --Kiểu mảng
Lớp 11 --chương 4 -- bài 11 --Kiểu mảng
 

More from Hồ Lợi

Tóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của cTóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của cHồ Lợi
 
Lect04 functions
Lect04 functionsLect04 functions
Lect04 functionsHồ Lợi
 
Ky thuatkhudequy
Ky thuatkhudequyKy thuatkhudequy
Ky thuatkhudequyHồ Lợi
 
Itt epc assignment
Itt epc assignmentItt epc assignment
Itt epc assignmentHồ Lợi
 
Huong danontapc
Huong danontapcHuong danontapc
Huong danontapcHồ Lợi
 
H hai epc_baitap
H hai epc_baitapH hai epc_baitap
H hai epc_baitapHồ Lợi
 
Giaotrinhbaitapkythuatlaptrinh
GiaotrinhbaitapkythuatlaptrinhGiaotrinhbaitapkythuatlaptrinh
GiaotrinhbaitapkythuatlaptrinhHồ Lợi
 
Giao trinh ky thuat lap trinh 2
Giao trinh ky thuat lap trinh 2Giao trinh ky thuat lap trinh 2
Giao trinh ky thuat lap trinh 2Hồ Lợi
 
Giao trinh c c++
Giao trinh c c++Giao trinh c c++
Giao trinh c c++Hồ Lợi
 
Epc assignment
Epc assignmentEpc assignment
Epc assignmentHồ Lợi
 
Epc test practical
Epc test practicalEpc test practical
Epc test practicalHồ Lợi
 
De thic++ --th
De thic++ --thDe thic++ --th
De thic++ --thHồ Lợi
 

More from Hồ Lợi (20)

Xu ly chuoi
Xu ly chuoiXu ly chuoi
Xu ly chuoi
 
Tóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của cTóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của c
 
T4
T4T4
T4
 
Nguyen lyoop
Nguyen lyoopNguyen lyoop
Nguyen lyoop
 
Lect04 functions
Lect04 functionsLect04 functions
Lect04 functions
 
Ky thuatkhudequy
Ky thuatkhudequyKy thuatkhudequy
Ky thuatkhudequy
 
Itt epc assignment
Itt epc assignmentItt epc assignment
Itt epc assignment
 
Huong danontapc
Huong danontapcHuong danontapc
Huong danontapc
 
H hai epc_baitap
H hai epc_baitapH hai epc_baitap
H hai epc_baitap
 
Gtrinh oop
Gtrinh oopGtrinh oop
Gtrinh oop
 
Giaotrinhbaitapkythuatlaptrinh
GiaotrinhbaitapkythuatlaptrinhGiaotrinhbaitapkythuatlaptrinh
Giaotrinhbaitapkythuatlaptrinh
 
Giao trinh ky thuat lap trinh 2
Giao trinh ky thuat lap trinh 2Giao trinh ky thuat lap trinh 2
Giao trinh ky thuat lap trinh 2
 
Giao trinh c c++
Giao trinh c c++Giao trinh c c++
Giao trinh c c++
 
File trong c_
File trong c_File trong c_
File trong c_
 
Epc assignment
Epc assignmentEpc assignment
Epc assignment
 
Epc test practical
Epc test practicalEpc test practical
Epc test practical
 
De thic++ --th
De thic++ --thDe thic++ --th
De thic++ --th
 
Dethi c++ -lt
Dethi c++ -ltDethi c++ -lt
Dethi c++ -lt
 
Debug trong c
Debug trong cDebug trong c
Debug trong c
 
D05 stl
D05 stlD05 stl
D05 stl
 

Bai3 timkiem sapxep

  • 1. 1 TÌM KIẾM & SẮP XẾP
  • 2. 2 Tìm kiếm Tìm kiếm tuần tự Tìm kiếm nhị phân
  • 3. 3 Ví dụ – Tìm vị trí X trong dãy //input: dãy (a, N), X //output: Vị trí của X, -1 nếu không có intint Search(int a[], int N, int X)Search(int a[], int N, int X) {{ for (int i = 0; i < N; i ++)for (int i = 0; i < N; i ++) if (a[i] == X)if (a[i] == X) return i;return i; returnreturn --1;1; }} Bài toán: Tìm vị trí X trên mảng a đang có N thành phần. Giải pháp: Tìm tuần tự
  • 4. 4 Tìm kiếm Tìm kiếm tuần tự (tìm kiếm tuyến tính) – Thời gian tồi nhất để thực hiện giải thuật:n x constant – Tỷ suất tăng của giải thuật là n – Độ phức tạp thuật toán O(n)
  • 5. 5 Ứng dụng – Loại bỏ một thành phần dữ liệu Bài toán: loại bỏ thành phần dữ liệu X ra khỏi mảng a đang có N thành phần. Hướng giải quyết: xác định vị trí của X, nếu tìm thấy thì dồn các phần tử ở phía sau lên để lấp vào chỗ trống. 2 trường hợp: – Dãy không có thứ tự: lấp phần tử cuối lên – Dãy đã thứ tự: dời tất cả các phần tử ở sau ví trí của X lên trước 1 vị trí.
  • 6. 6 N = 8 Ứng dụng – Loại bỏ X ra khỏi dãy tăng Loại 5 khỏi (a, 8) N = 7 pos Tìm vị trí của 5 X Dồn các vị trí 4, 5, 6, 7 lên
  • 7. 7 Ứng dụng – Loại bỏ X ra khỏi dãy tăng //input: dãy (a, N), X //output: dãy (a, N) đã loại bỏ 1 thành phần X intint Remove(int a[], int &N, int X)Remove(int a[], int &N, int X) {{ int pos = Search(a, N, X);int pos = Search(a, N, X); if (pos ==if (pos == --1)1) //không c//không cóó X trong dãyX trong dãy return 0;return 0; NN ----;; for (; (pos < N); pos ++)for (; (pos < N); pos ++) a[pos] = a[pos + 1];a[pos] = a[pos + 1]; return 1;return 1; }}
  • 8. 8 Tìm kiếm Tìm kiếm nhị phân – Bài toán: Với một dãy số đã sắp xếp, chúng ta có thể áp dụng phương pháp tìm kiếm nhị phân.
  • 9. 9 Tìm kiếm nhị phân Phương pháp tìm:ứng dụng cho các dãy đã sắp xếp thứ tự Kiểm tra phần tử giữa của dãy – Nếu khóa cần tìm nhỏ hơn, tiến sang trái – Nếu trùng khớp: Kết thúc! – Nếu khóa cần tìm lớn hơn, tiến sang phải Bạn có thể chia n thành hai phần: tốn thời gian log2n Bởi vậy tìm kiếm nhị phân tốn thời gian = c log2n Độ phức tạp tính toán của thuật toán là O( log n ) n n 2 < n 4 n 8
  • 10. 10 Ví dụ – Tìm vị trí X trong dãy //input: dãy (a, N), X //output: Vị trí của X, -1 nếu không có intint BinarySearch(int a[], int N, int x)BinarySearch(int a[], int N, int x) {int left=0, right=N{int left=0, right=N--1, mid;1, mid; do{do{ mid=(left+right)/2;mid=(left+right)/2; if(x==a[mid]) return mid;// x tai midif(x==a[mid]) return mid;// x tai mid else if (x<a[mid]) right=midelse if (x<a[mid]) right=mid--1;1; else left= mid+1;else left= mid+1; }while (left<=right);}while (left<=right); returnreturn --1;1; }} Bài toán: Tìm vị trí X trên mảng a đang có N thành phần ( mảng a sắp tăng dần). Giải pháp: Tìm nhị phân
  • 11. 11 Tìm kiếm tuần tự & Tìm kiếm nhị phân Chọn lựa phương pháp – Tuần tự:Thời gian thực hiện tồi nhất: c1 n – Tìm kiếm nhị phân:Thời gian thực hiện tồi nhất: c2 log2n Compare n with logn 0 10 20 30 40 50 60 0 10 20 30 40 50 60 n Time 4 log n n Bài toán nhỏ - Chúng tôi không quan tâm! Các bài toán lớn - Nhận thấy TK nhị phân tốt hơn nhiều n 4log2nVới bài toán nhỏ: Tìm kiếm nhị phân có T(n) cao hơn
  • 12. 12 Tìm kiếm Tìm kiếm tuần tự – Tỷ suất tăng: n – Độ phức tạp thuật toán: O(n) – Được sử dụng tốt cho các dãy chưa sắp xếp Tìm kiếm nhị phân – Cho các dãy đã sắp xếp – Tỷ suất tăng: log2 n – Độ phức tạp: O(log n) Trường hợp dãy chưa sắp xếp: phải cộng thêm chi phí sắp xếp dãy, do đó (không nên dùng tìm kiếm nhị phân)
  • 14. 14 Mục tiêu Sau khi hoàn tất bài học này bạn cần phải: Hiểu các giải thuật sắp xếp. Vận dụng được giải thuật để minh họa việc sắp xếp. Hiểu các lưu đồ của các giải thuật sắp xếp. Hiểu các chương trình sắp xếp. Hiểu được việc đánh giá các giải thuật.
  • 15. 15 Tầm quan trọng của bài toán sắp xếp Sắp xếp một danh sách các đối tượng theo một thứ tự nào đó là một bài toán thường được vận dụng trong các ứng dụng tin học. Sắp xếp là một yêu cầu không thể thiếu trong khi thiết kế các phần mềm. Do đó việc nghiên cứu các phương pháp sắp xếp là rất cần thiết để vận dụng trong khi lập trình.
  • 16. 16 Sắp xếp trong và sắp xếp ngoài Sắp xếp trong là sự sắp xếp dữ liệu được tổ chức trong bộ nhớ trong của máy tính. Các đối tượng cần được sắp xếp là các mẩu tin gồm một hoặc nhiều trường. Một trong các trường được gọi là khóa (key), kiểu của nó là một kiểu có quan hệ thứ tự (như các kiểu số nguyên, số thực, chuỗi ký tự...). Danh sách các đối tượng cần sắp xếp sẽ là một mảng của các mẩu tin vừa nói ở trên. Mục đích của việc sắp xếp là tổ chức lại các mẩu tin sao cho các khóa của chúng được sắp thứ tự tương ứng với quy luật sắp xếp. Một cách mặc nhiên, quy luật sắp xếp là thứ tự không giảm. Khi cần sắp xếp theo thứ tự không tăng thì phải nói rõ. Sắp xếp ngoài là sự sắp xếp được sử dụng khi số lượng đối tượng cần sắp xếp lớn không thể lưu trữ trong bộ nhớ trong mà phải lưu trữ trên bộ nhớ ngoài.
  • 17. 17 Tổ chức dữ liệu và ngôn ngữ cài đặt Ðể trình bày các ví dụ minh họa chúng ta sẽ dùng C (Turbo C++, Version 3.0) làm ngôn ngữ thể hiện và sử dụng khai báo sau. const int n = 10; typedef int keytype; typedef float othertype; typedef struct recordtype { keytype key; othertype otherfields; }; recordtype a[n]; /* khai bao mang a co n phan tu */
  • 18. 18 Tổ chức dữ liệu và ngôn ngữ cài đặt (tt) void Swap(recordtype *x, recordtype *y) { recordtype temp; temp = *x; *x = *y; *y = temp; } Cần thấy rằng thủ tục Swap lấy O(1) thời gian vì chỉ thực hiện 3 lệnh gán nối tiếp nhau.
  • 19. 19 Giải thuật sắp xếp chọn (Selection Sort) Bước 0, chọn phần tử có khóa nhỏ nhất trong n phần tử từ a[0] đến a[n-1] và hoán vị nó với phần tử a[0]. Bước 1, chọn phần tử có khóa nhỏ nhất trong n-1 phần tử từ a[1] đến a[n-1] và hoán vị nó với a[1]. Tổng quát ở bước thứ i, chọn phần tử có khoá nhỏ nhất trong n-i phần tử từ a[i] đến a[n-1] và hoán vị nó với a[i]. Sau n-1 bước này thì mảng đã được sắp xếp.
  • 20. 20 Phương pháp chọn phần tử Đầu tiên ta đặt khoá nhỏ nhất là khoá của a[i] (lowkey = a[i].key) và chỉ số của phần tử có khoá nhỏ nhất là i (lowindex = i). Xét các phần tử a[j] (với j từ i+1 đến n-1), nếu khoá của a[j] nhỏ hơn khoá nhỏ nhất (a[j].key < lowkey) thì đặt lại lại khoá nhỏ nhất là khoá của a[j] (lowkey = a[j].key) và chỉ số của phần tử có khoá nhỏ nhất là j (lowindex = j). Khi đã xét hết các a[j] (j>n-1) thì phần tử có khoá nhỏ nhất là a[lowindex].
  • 21. 21 Ví dụ sắp xếp chọn 1210109965322Kết quả 1210Bước 8 101210Bước 7 1012109Bước 6 10910129Bước 5 109109126Bước 4 6910912105Bước 3 59109121063Bước 2 391091210652Bước 1 3910912102562Bước 0 3910912102265Ban đầu a[9]a[8]a[7]a[6]a[5]a[4]a[3]a[2]a[1]a[0] Khóa Bước
  • 22. 22 Lưu đồ sắp xếp chọn Begin i = 0 i<=n-2 lowindex = i lowkey = a[i].key j<=n-1 i = i+1 a[j].key<lowkey lowindex = j lowkey = a[j].key j = j+1 S j = i+1 End swap(a[i],a[lowindex]) S Đ S Đ Đ
  • 23. 23 Chương trình sắp xếp chọn void SelectionSort(void) { int i,j,lowindex; keytype lowkey; /*1*/ for (i=0; i<=n-2; i++) { /*2*/ lowindex = i; /*3*/ lowkey = a[i].key; /*4*/ for (j = i+1; j <= n-1; j++) /*5*/ if (a[j].key < lowkey) { /*6*/ lowkey = a[j].key; /*7*/ lowindex = j; } /*8*/ Swap(&a[i],&a[lowindex]); } }
  • 24. 24 Đánh giá sắp xếp chọn Hàm Swap tốn O(1). Toàn bộ chương trình chỉ bao gồm lệnh /*1*/. Lệnh /*1*/ chứa các lệnh “đồng cấp” /*2*/, /*3*/, /*4*/ và /*8*/, trong đó các lệnh /*2*/, /*3*/ và /*8*/ đều tốn thời gian O(1). Lệnh /*6*/ và /*7*/ đều tốn O(1) nên lệnh /*5*/ tốn O(1). Vòng lặp /*4*/ thực hiện n-i-1 lần, vì j chạy từ i+1 đến n-1, mỗi lần lấy O(1), nên lấy O(n-i-1) thời gian. Gọi T(n) là thời gian thực hiện của chương trình, thì T(n) là thời gian thực hiện lệnh /*1*/. Mà lệnh /*1*/ có i chạy từ 0 đến n-2 nên ta có: )O(n 2 1)-n(n 1)-i-(nT(n) 2 2-n 0=i
  • 25. 25 Giải thuật sắp xếp xen (Insertion Sort) Trước hết ta xem phần tử a[0] là một dãy đã có thứ tự. Bước 1, xen phần tử a[1] vào danh sách đã có thứ tự a[0] sao cho a[0], a[1] là một danh sách có thứ tự. Bước 2, xen phần tử a[2] vào danh sách đã có thứ tự a[0], a[1] sao cho a[0], a[1], a[2] là một danh sách có thứ tự. Tổng quát, bước i, xen phần tử a[i] vào danh sách đã có thứ tự a[0], a[1], … a[i-1] sao cho a[0], a[1],.. a[i] là một danh sách có thứ tự. Sau n-1 bước thì kết thúc.
  • 26. 26 Phương pháp xen Phần tử đang xét a[j] sẽ được xen vào vị trí thích hợp trong danh sách các phần tử đã được sắp trước đó a[0],a[1],..a[j-1]: So sánh khoá của a[j] với khoá của a[j-1] đứng ngay trước nó. Nếu khoá của a[j] nhỏ hơn khoá của a[j-1] thì hoán đổi a[j-1] và a[j] cho nhau và tiếp tục so sánh khoá của a[j-1] (lúc này a[j-1] chứa nội dung của a[j]) với khoá của a[j-2] đứng ngay trước nó...
  • 27. 27 Ví dụ sắp xếp xen 1210109965322Bước 9 121010996522Bước 8 12101096522Bước 7 121096522Bước 6 12106522Bước 5 106522Bước 4 6522Bước 3 652Bước 2 65Bước 1 3910912102265Ban đầu a[9]a[8]A[7]a[6]a[5]a[4]a[3]a[2]a[1]a[0]Khóa Bước
  • 28. 28 Lưu đồ sắp xếp xen Begin i = 1 i<=n-1 (j>0) and (a[j].key < a[j-1].key) i = i+1 j = i End swap(a[j],a[j-1]) j = j-1 S Đ Đ S
  • 29. 29 Chương trình sắp xếp xen void InsertionSort(void) { int i,j; /*1*/ for (i = 1; i<= n-1; i++) { /*2*/ j = i; /*3*/ while ((j>0) && (a[j].key < a[j-1].key)) { /*4*/ Swap(&a[j], &a[j-1]); /*5*/ j= j-1; } } }
  • 30. 30 Đánh giá sắp xếp xen Các lệnh /*4*/ và /*5*/ đều lấy O(1). Vòng lặp /*3*/, trong trường hợp xấu nhất, chạy i lần (j giảm từ i đến 1), mỗi lần tốn O(1) nên /*3*/ lấy i thời gian. Lệnh /*2*/ và /*3*/ là hai lệnh nối tiếp nhau, lệnh /*2*/ lấy O(1) nên cả hai lệnh này lấy i. Vòng lặp /*1*/ có i chạy từ 1 đến n-1 nên ta có: )O(n 2 1)-n(n iT(n) 2 1-n 1i
  • 31. 31 Giải thuật sắp xếp “nổi bọt” (Bubble Sort) Bước 1: Xét các phần tử a[j] (j giảm từ n-1 đến 1), so sánh khoá của a[j] với khoá của a[j-1]. Nếu khoá của a[j] nhỏ hơn khoá của a[j-1] thì hoán đổi a[j] và a[j-1] cho nhau. Sau bước này thì a[0] có khoá nhỏ nhất. Bước 2: Xét các phần tử a[j] (j giảm từ n-1 đến 2), so sánh khoá của a[j] với khoá của a[j-1]. Nếu khoá của a[j] nhỏ hơn khoá của a[j-1] thì hoán đổi a[j] và a[j-1] cho nhau. Sau bước này thì a[1] có khoá nhỏ thứ 2. … Sau n-1 bước thì kết thúc.
  • 32. 32 Ví dụ sắp xếp “nổi bọt” 1210109965322Kết quả 1210Bước 9 121010Bước 8 1210109Bước 7 12101099Bước 6 121010996Bước 5 1210109965Bước 4 10121099653Bước 3 109121093652Bước 2 9109121032652Bước 1 3910912102265Ban đầu a[9]a[8]a[7]a[6]A[5]a[4]a[3]a[2]a[1]a[0] Khóa Bước
  • 33. 33 Lưu đồ sắp xếp nổi bọt Begin i = 0 i<=n-2 i = i+1 j = n-1 End swap(a[j],a[j-1]) S Đ Đ S a[j].key < a[j-1].key j>= i+1 Đ j = j-1 S
  • 34. 34 Chương trình sắp xếp “nổi bọt” void BubbleSort(void) { int i,j; /*1*/ for(i= 0; i<= n-2; i++) /*2*/ for(j=n-1;j>=i+1; j--) /*3*/ if (a[j].key < a[j-1].key) /*4*/ Swap(&a[j],&a[j-1]); } Begin i = 0 i<=n-2 i = i+1 j = n-1 End swap(a[j],a[j-1]) S Đ Đ S a[j].key < a[j-1].key j>= i+1 Đ j = j-1 S
  • 35. 35 Ý tưởng của QuickSort Chọn một giá trị khóa v làm chốt (pivot). Phân hoạch dãy a[0]..a[n-1] thành hai mảng con "bên trái" và "bên phải". Mảng con "bên trái" bao gồm các phần tử có khóa nhỏ hơn chốt, mảng con "bên phải" bao gồm các phần tử có khóa lớn hơn hoặc bằng chốt. Sắp xếp mảng con “bên trái” và mảng con “bên phải”. Sau khi đã sắp xếp được mảng con “bên trái” và mảng con “bên phải” thì mảng đã cho sẽ được sắp bởi vì tất cả các khóa trong mảng con “bên trái” đều nhỏ hơn các khóa trong mảng con “bên phải”. Việc sắp xếp các mảng con “bên trái” và “bên phải” cũng được tiến hành bằng phương pháp nói trên. Một mảng chỉ gồm một phần tử hoặc gồm nhiều phần tử có khóa bằng nhau thì đã có thứ tự.
  • 36. 36 Phương pháp chọn chốt Chọn giá trị khóa lớn nhất trong hai phần tử có khóa khác nhau đầu tiên kể từ trái qua. Nếu mảng chỉ gồm một phần tử hay gồm nhiều phần tử có khóa bằng nhau thì không có chốt. Ví dụ: Chọn chốt trong các mảng sau – Cho mảng gồm các phần tử có khoá là 6, 6, 5, 8, 7, 4, ta chọn chốt là 6 (khoá của phần tử đầu tiên). – Cho mảng gồm các phần tử có khoá là 6, 6, 7, 5, 7, 4, ta chọn chốt là 7 (khoá của phần tử thứ 3). – Cho mảng gồm các phần tử có khoá là 6, 6, 6, 6, 6, 6 thì không có chốt (các phần tử có khoá bằng nhau). – Cho mảng gồm một phần tử có khoá là 6 thì không có chốt (do chỉ có một phần tử).
  • 37. 37 Phương pháp phân hoạch Ðể phân hoạch mảng ta dùng 2 "con nháy" L và R trong đó L từ bên trái và R từ bên phải. Ta cho L chạy sang phải cho tới khi gặp phần tử có khóa ≥ chốt Cho R chạy sang trái cho tới khi gặp phần tử có khóa < chốt. Tại chỗ dừng của L và R nếu L < R thì hoán vị a[L],a[R]. Lặp lại quá trình dịch sang phải, sang trái của 2 "con nháy" L và R cho đến khi L > R. Khi đó L sẽ là điểm phân hoạch, cụ thể là a[L] là phần tử đầu tiên của mảng con “bên phải”.
  • 38. 38 Ví dụ về phân hoạch 4151812510285Khoá 9876543210Chỉ số Chốt p = 8 L=0 R=9
  • 39. 39 Ví dụ về phân hoạch 4151812510285Khoá 9876543210Chỉ số L=1 Chốt p = 8 R=9
  • 40. 40 Ví dụ về phân hoạch 8151812510245Khoá 9876543210Chỉ số L=1 Chốt p = 8 R=9
  • 41. 41 Ví dụ về phân hoạch 8151812510245Khoá 9876543210Chỉ số L=2 Chốt p = 8 R=9
  • 42. 42 Ví dụ về phân hoạch 8151812510245Khoá 9876543210Chỉ số L=3 Chốt p = 8 R=9
  • 43. 43 Ví dụ về phân hoạch 8151812510245Khoá 9876543210Chỉ số L=3 Chốt p = 8 R=8
  • 44. 44 Ví dụ về phân hoạch 8151812510245Khoá 9876543210Chỉ số L=3 Chốt p = 8 R=7
  • 45. 45 Ví dụ về phân hoạch 8151081251245Khoá 9876543210Chỉ số L=3 Chốt p = 8 R=7
  • 46. 46 Ví dụ về phân hoạch 8151081251245Khoá 9876543210Chỉ số L=4 Chốt p = 8 R=7
  • 47. 47 Ví dụ về phân hoạch 8151081251245Khoá 9876543210Chỉ số L=5 Chốt p = 8 R=7
  • 48. 48 Ví dụ về phân hoạch 8151081251245Khoá 9876543210Chỉ số L=5 Chốt p = 8 R=6
  • 49. 49 Ví dụ về phân hoạch 8151081251245Khoá 9876543210Chỉ số L=5 Chốt p = 8 R=5
  • 50. 50 Ví dụ về phân hoạch 8151081251245Khoá 9876543210Chỉ số L=5 Chốt p = 8 R=4 51245 43210 81510812 98765
  • 51. 51 Giải thuật QuickSort Ðể sắp xếp mảng a[i]..a[j] ta làm các bước sau: – Xác định chốt. – Phân hoạch mảng đã cho thành hai mảng con a[i]..a[k-1] và a[k]..a[j]. – Sắp xếp mảng a[i]..a[k-1] (Ðệ quy). – Sắp xếp mảng a[k]..a[j] (Ðệ quy). Đệ quy sẽ dừng khi không còn tìm thấy chốt.
  • 52. 52 Ví dụ về QuickSort Chốt p = 8 51245 81510812 Chốt p = 5 4151812510285Khoá 9876543210Chỉ số
  • 53. 53 Ví dụ về QuickSort 8151081251245Khoá 9876543210Chỉ số Chốt p = 8 51 5 245 1 81510812 Chốt p = 5 241 55 Chốt p = 4
  • 54. 54 Ví dụ về QuickSort 8151081251245Khoá 9876543210Chỉ số Chốt p = 8 51 5 245 1 81510812 Chốt p = 5 2 4 4 2 1 55 Chốt p = 4 21 4 Chốt p = 2 1 2 xong xong xong xong Chốt p = 12
  • 55. 55 Ví dụ về QuickSort 8151081251245Khoá 9876543210Chỉ số Chốt p = 8 51 5 245 1 8 12 1510812 8 Chốt p = 5 2 4 4 2 1 55 Chốt p = 4 21 4 Chốt p = 2 1 2 xong xong xong xong Chốt p = 12 1088 1215 Chốt p = 10 88 10 xong xong Chốt p = 15
  • 56. 56 Ví dụ về QuickSort 8151081251245Khoá 9876543210Chỉ số Chốt p = 8 51 5 245 1 8 12 1510812 8 Chốt p = 5 2 4 4 2 1 55 Chốt p = 4 21 4 Chốt p = 2 1 2 xong xong xong xong Chốt p = 12 1088 12 15 15 12 Chốt p = 10 88 10 xong xong Chốt p = 15 12 15 xong xong
  • 57. 57 Lưu đồ hàm FindPivot Begin k = i+1 firstkey = a[i].key (k<=j) and (a[k].key == firstkey k > j a[k].key>firstkey k = k+1 End Đ Đ Đ S S return -1 return i return k i, j S
  • 58. 58 Chương trình hàm FindPivot int FindPivot(int i,int j) { keytype firstkey; int k ; k = i+1; firstkey = a[i].key; while ( (k <= j) && (a[k].key == firstkey) ) k++; if (k > j) return -1; else if (a[k].key>firstkey) return k; else return i; } Begin k = i+1 firstkey = a[i].key (k<=j) and (a[k].key == firstkey k > j a[k].key>firstkey k = k+1 End Đ Đ Đ S S return -1 return i return k i, j S
  • 59. 59 Phân tích hàm FindPivot int FindPivot(int i,int j) { keytype firstkey; int k ; /*1*/ k = i+1; /*2*/ firstkey = a[i].key; /*3*/ while ( (k <= j) && (a[k].key == firstkey) ) k++; /*4*/ if (k > j) return -1; else /*5*/ if (a[k].key>firstkey) return k; else return i; } /*1*/, /*2*/, /*3*/ và /*4*/ nối tiếp nhau. Lệnh WHILE là tốn nhiều thời gian nhất. Trong trường hợp xấu nhất thì k chạy từ i+1 đến j, tức là vòng lặp thực hiện j-i lần, mỗi lần O(1) do đó tốn j-i Đặc biệt khi i=0 và j=n- 1, thì thời gian thực hiện là n-1 hay T(n) = O(n).
  • 60. 60 Lưu đồ hàm Partition Begin L = i; R = j L <= R a[R].key >= pivot a[L].key < pivot L = L+1 End Đ ĐS S return L i, j, pivot S R = R-1L < R Swap(a[L], a[R]) Đ S Đ
  • 61. 61 Hàm Partition int Partition(int i,int j, keytype pivot) { int L,R; /*1*/ L = i; /*2*/ R = j; /*3*/ while (L <= R) { /*4*/ while (a[L].key < pivot) L++; /*5*/ while (a[R].key >= pivot) R--; /*6*/ if (L<R) Swap(&a[L],&a[R]); } /*7*/ return L; /*Tra ve diem phan hoach*/ } Begin L = i; R = j L <= R a[R].key >= pivot a[L].key < pivot L = L+1 End Đ ĐS S return L i, j, pivot S R = R-1L < R Swap(a[L], a[R]) Đ S Đ
  • 62. 62 Phân tích hàm Partition int Partition(int i,int j, keytype pivot) { int L,R; /*1*/ L = i; /*2*/ R = j; /*3*/ while (L <= R) { /*4*/ while (a[L].key < pivot) L++; /*5*/ while (a[R].key >= pivot) R--; /*6*/ if (L<R) Swap(&a[L],&a[R]); } /*7*/ return L; } /*1*/, /*2*/, /*3*/ và /*7*/ nối tiếp nhau Thời gian thực hiện của /*3*/ là lớn nhất. Các lệnh /*4*/, /*5*/ và /*6*/ là thân của lệnh /*3*/, trong đó lệnh /*6*/ lấy O(1). Lệnh /*4*/ và lệnh /*5*/ thực hiện việc di chuyển L sang phải và R sang trái cho đến khi L và R gặp nhau, thực chất là duyệt các phần tử mảng, mỗi phần tử một lần, mỗi lần tốn O(1) thời gian. Tổng cộng việc duyệt này tốn j-i thời gian. Vòng lặp /*3*/ thực chất là để xét xem khi nào thì duyệt xong, do đó thời gian thực hiện của lệnh /*3*/ chính là thời gian thực hiện của hai lệnh /*4*/ và /*5*/ và do đó là j-i. Đặc biệt khi i=0 và j=n-1 ta có T(n) = O(n).
  • 63. 63 Hàm QuickSort void QuickSort(int i,int j) { keytype pivot; int pivotindex, k; pivotindex = FindPivot(i,j); if (pivotindex != -1) { pivot = a[pivotindex].key; k = Partition(i,j,pivot); QuickSort(i,k-1); QuickSort(k,j); } }
  • 64. 64 Đánh giá QuickSort (Trường hợp xấu nhất) Giả sử các giá trị khóa của mảng khác nhau nên hàm FindPivot luôn tìm được chốt và đệ quy chỉ dừng khi kích thước bài toán bằng 1. Gọi T(n) là thời gian thức hiện việc QuickSort mảng có n phần tử. Thời gian tìm chốt và phân hoạch mảng là O(n) = n. Khi n = 1, thủ tục QuickSort chỉ làm một nhiệm vụ duy nhất là gọi hàm Findpivot với kích thước bằng 1, hàm này tốn thời gian O(1) =1. Trong trường hợp xấu nhất, phân hoạch lệch. Khi đó ta có thể thành lập phương trình đệ quy như sau: 1>nnêun+T(1)+1)-T(n 1=nnêu1 T(n) Giải PT này ta được T(n) =O(n2)
  • 65. 65 Đánh giá QuickSort (Trường hợp tốt nhất) Trong trường hợp tốt nhất khi ta chọn được chốt sao cho hai mảng con có kích thước bằng nhau và bằng n/2. Lúc đó ta có phương trình đệ quy như sau: Giải PT này ta được T(n) =O(nlogn) 1nnêun) 2 n 2T( 1nnêu1 T(n)
  • 66. 66 HeapSort: Ðịnh nghĩa Heap Cây sắp thứ tự bộ phận hay còn gọi là heap là cây nhị phân mà giá trị tại mỗi nút (khác nút lá) đều không lớn hơn giá trị của các con của nó. Ta có nhận xét rằng nút gốc của cây sắp thứ tự bộ phận có giá trị nhỏ nhất.
  • 67. 67 Ví dụ về heap 2 3 6 5 9 6 7 7 6 9
  • 68. 68 HeapSort : Ý tưởng giải thuật (1) Xem mảng ban đầu là một cây nhị phân. Mỗi nút trên cây lưu trữ một phần tử mảng, trong đó a[0] là nút gốc và mỗi nút không là nút lá a[i] có con trái là a[2i+1] và con phải là a[2i+2]. Với cách tổ chức này thì cây nhị phân thu được sẽ có các nút trong là các nút a[0], …, a[(n- 2)/2]. Tất cả các nút trong đều có 2 con, ngoại trừ nút a[(n-2)/2] có thể chỉ có một con trái (trong trường hợp n là một số chẵn). (2) Sắp xếp cây ban đầu thành một heap căn cứ vào giá trị khoá của các nút. (3) Hoán đổi nút gốc a[0] cho cho nút lá cuối cùng. (4) Sắp lại cây sau khi đã bỏ đi nút lá cuối cùng để nó trở thành một heap mới. Lặp lại quá trình (3) và (4) cho tới khi cây chỉ còn một nút. Nút này cùng với các nút lá đã bỏ đi tạo thành một mảng sắp theo thứ tự giảm.
  • 69. 69 Thiết kế hàm PushDown PushDown nhận vào 2 tham số first và last để đẩy nút first xuống. Giả sử a[first],..,a[last] đã đúng vị trí của một heap, ngoại trừ a[first]. PushDown dùng để đẩy phần tử a[first] xuống đúng vị trí của nó trong cây. Xét a[first], có các khả năng có thể xẩy ra: – Nếu a[first] chỉ có một con trái và nếu khoá của nó lớn hơn khoá của con trái (a[first].key > a[2*first+1].key) thì hoán đổi a[first] cho con trái của nó và kết thúc. – Nếu a[first] có khoá lớn hơn con trái của nó và khoá của con trái không lớn hơn khoá của con phải thì hoán đổi a[first] cho con trái của nó, việc này có thể gây ra tình trạng con trái sẽ không đúng vị trí nên phải xem xét lại con trái để có thể đẩy xuống. – Ngược lại, nếu a[first] có khoá lớn hơn khoá của con phải của nó và khoá của con phải nhỏ hơn khoá của con trái thì hoán đổi a[first] cho con phải của nó, việc này có thể gây ra tình trạng con phải sẽ không đúng vị trí nên phải tiếp tục xem xét con phải để có thể đẩy xuống. – Nếu tất cả các trường hợp trên đều không xẩy ra thì a[first] đã đúng vị trí.
  • 70. 70 Lưu đồ hàm PushDown Begin r = first r <= (last-1)/2 a[r].key > a[last].key last==2*r+1 r = last End Đ Đ S S first, last S swap(a[r],a[last]) a[r].key > a[2*r+1].key and a[2*r+1].key <= a[2*r+2].key swap(a[r], a[2*r+1]) r = 2*r+1 Đ S Đ S a[r].key > a[2*r+2].key and a[2*r+2].key < a[2*r+1].key swap(a[r], a[2*r+2]) r = 2*r+2 Đ r = last
  • 71. 71 Chương trình hàm Pushdown void PushDown(int first,int last) { int r; r= first; while (r <= (last-1)/2) if (last == 2*r+1) { if (a[r].key > a[last].key) Swap(&a[r],&a[last]); r = last; } else if ((a[r].key>a[2*r+1].key) && (a[2*r+1].key<=a[2*r+2].key)) { Swap(&a[r],&a[2*r+1]); r = 2*r+1 ; } else if ((a[r].key>a[2*r+2].key) && (a[2*r+2].key<a[2*r+1].key)) { Swap(&a[r],&a[2*r+2]); r = 2*r+2 ; } else r = last; }
  • 72. 72 Phân tích hàm PushDown Ta xét PushDown(0,n-1), tức là PushDown trên cây có n nút. PushDown chỉ duyệt trên một nhánh nào đó của cây nhị phân, tức là sau mỗi lần lặp thì số nút còn lại một nửa. Một cách cụ thể, trước hết PushDown trên cây có n nút; Sau lần lặp thứ nhất, PushDown trên cây có n/2 nút; Sau lần lặp thứ hai, PushDown trên cây có n/4 nút;… Tổng quát, Sau lần lặp thứ i, PushDown trên cây có n/2i nút. Như vậy, trong trường hợp xấu nhất (luôn phải thực hiện việc đẩy xuống) thì lệnh lặp while phải thực hiện i lần sao chon/2i = 1 tức là i=logn (i=logn là số lần lặp của lệnh while, trong trường hợp xấu nhất). Mà mỗi lần lặp chỉ thực hiện một lệnh IF với thân lệnh IF là lời gọi Swap và lệnh gán, do đó tốn O(1) = 1 đơn vị thời gian. Từ đó ta thấy PushDown lấy O(logn) để đẩy xuống một nút trong cây có n nút.
  • 73. 73 Chương trình hàm HeapSort void HeapSort(void) { int i; /*1*/ for(i = (n-2)/2; i>=0; i--) /*2*/ PushDown(i,n-1); /*3*/ for(i = n-1; i>=2; i--) { /*4*/ Swap(&a[0],&a[i]); /*5*/ PushDown(0,i-1); } /*6*/ Swap(&a[0],&a[1]); }
  • 74. 74 Phân tích HeapSort Hàm PushDown lấy O(logn). Trong HeapSort, – Vòng lặp /*1*/-/*2*/ lặp (n-2)/2+1 lần mà mỗi lần lấy O(logn) nên thời gian thực hiện /*1*/-/*2*/ là O(n logn). – Vòng lặp /*3*/-/*5*/ lặp n-2 lần, mỗi lần lấy O(logn) nên thời gian thực hiện của /*3*/-/*5*/ là O(n logn). Thời gian thực hiện HeapSort là O(nlogn).
  • 75. 75 HeapSort: Trình bày bằng bảng Tạo Heap 3910912102265Ban đầu a[9]a[8]a[7]a[6]A[5]a[4]a[3]a[2]a[1]a[0] Khóa Bước
  • 76. 76
  • 77. 77
  • 78. 78
  • 79. 79
  • 80. 80
  • 81. 81