phần tử
int mid = (first +last)/2;
MergeSort(a,first,mid);
MergeSort(a, mid+1, last);
Merge(a,first, last);
}
}
Merge Sort – Ví dụ
divide
6 3 9 1 5 4 7 2
divide
divide
7 2
6 3 9 1 5 4 7 2
6 3
9 1
divide
divide
divide
divide
5 4
merge
merge
merge
merge
6 3 9 1 5 4 7 2
4 5
merge
merge
2 7 1 9 3 6
merge
1 2 3 4 5 7 8 9
1 3 6 9 2 4 5 7
Phân tích thuật toán Merge
Trường hợp xấu nhất
Phân tích thuật toán Merge
0 k-1
......
0 k-1
......
Trộn hai mảng kích cỡ k
0 2k-1
......
Tốt nhất:
Tất cả phần tử trong mảng trái nhỏ hơn phần tử trong mảng phải.
Số phép so sánh: k + 1
Xấu nhất:
i = k-1 và j = k-1
Số phép so sánh: 2k
Phân tích Merge Sort
Các cấp gọi đệ qui của mảng có 8 phần tử
Phân tích Merge Sort
2m
2m-1
2m-1
level 0 : 1 merge (size 2m-1)
level 1 : 2 merges (size 2m-2)
2m-2 2m-2 2m-2
2m-2
.
.
.
.
.
.
level 2 : 4 merges (size 2m-3)
20
20
level m-1 : 2m-1 merges (size 20)
. . . . . . . . . . . . . . . . .
level m
Đánh giá Merge Sort
Xấu nhất
Số phép so sánh:
= (2*20 )*2m-1 + (2*21)*2m-2 + ... + (2*2m-1)*20
= 2m + 2m + ... + 2m
( m hạng tử )
= m*2m
Thay m = log n
Số phép so sánh:
= n * log2n
O (n * log2n )
Đánh giá Merge Sort
Merge Sort là thuật toán hiệu quả xét trên phương
diện độ phức tạp tính toán và thời gian.
Độ phức tạp trong cả trường hợp tốt nhất và xấu nhất: O (n * log2n )
Để trộn hai mảng con của một mảng cho trước, đòi
hỏi một mảng có kích cỡ bằng kích cỡ mảng ban
đầu .
Quick Sort
Sort (26, 33, 35, 29, 19, 12, 22)
Phân thành (19, 12, 22) và (33,35,29) với pivot=26
Sort (19, 12, 22)
Phân thành (12) và (22) với pivot=19
Sort (12)
Sort (22)
Combine into (12, 19, 22)
Sort (33, 35, 29)
Phân thành (29) và (35) với pivot=33
Sort (29)
Sort (35)
Combine into (29, 33, 35)
Combine into (12, 19, 22, 26, 29, 33, 35)
Quick Sort
Algorithm Quick Sort
Input: mảng cần sắp
Output: mảng đã được sắp xếp
1. if (có ít nhất 2 phần tử)
//Phân hoạch mảngthành 3 phần:
//- Phần nhỏ hơn phần tử giữa
//- Phần tử giữa
//- Phần lớn hơn phần tử giữa
1.1. Phân hoạch mảng thành 3 phần
1.2. Call QuickSort cho phần bên trái
1.3. Call QickSort cho phần bên phải
//Chỉ cần ghép lại là thành danh sách có thứ tự
End
Quick Sort
void QuickSort(int a[], int low, int high){
if(low
int pivot_pos = Partition(a, low, high);
QuickSort(a,low,pivot_pos);
QuickSort(a, pivot_pos+1, high);
}
}
Phân hoạch cho Quick Sort
Phân hoạch cho Quick Sort
Partition Quick Sort
int Partition(int a[], int low, int high){
int mid = (low + high)/2;
Swap(a[low], a[mid]);
int pivot = a[low];
int last_small = low;
for(int i= low+1; i<=high; i++)
if(a[i]
last_small ++; Swap(a[last_small],a[i]);
}
Swap(a[low],a[last_small]);
return last_small;
}
Ví dụ Quick Sort
QuickSort(0,6)
0
1
2
3
4
5
6
pivot
26 pivot_position = Partition(0,6) = 3
19 35 33 26 29 12 22
low=0 high=6
last_small
mid=(low+high)/2=3
pivot_position
QuickSort(0,2) index
QuickSort(4,6)
Ví dụ Quick Sort
QuickSort(0,2)
0
1
2
3
4
5
6
pivot
19 pivot_position = Partition(0,2) = 1
22 19 12 26 29 33 35
low=0 high=2
mid=(low+high)/2=1
last_small
index
(Không làm gì cả)
QuickSort(0,0)
QuickSort(2,2) pivot_position
Ví dụ Quick Sort
QuickSort(4,6)
0
1
2
3
4
5
6
pivot
33 pivot_position = Partition(4,6) = 5
12 19 22 26 29 33 35
low=4 high=6
mid=(low+high)/2=5
last_small
index
(Không làm gì cả)
QuickSort(4,4)
QuickSort(6,6) pivot_position
Các trường hợp của Quick sort
Đánh giá Quick Sort
Trường hợp xấu nhất:
Một bên rỗng và một bên là n-1 phần tử => n(n-1)/2
Chọn phần tử pivot:
Đầu (hay cuối): trường hợp xấu xảy ra khi danh sách đang
có thứ tự (hoặc thứ tự ngược)
Ở trung tâm, hoặc ngẫu nhiên: trường hợp xấu khó xảy ra
Trường hợp trung bình:
C(n) = 2n ln n + O(n) ≈ 1.39 n lg n + O(n) ≈O(nlogn)
Heap và Heap Sort
Heap (định nghĩa lại):
Mảng có n phần tử (từ 0 đến n-1)
ak ≥ a2k+1 và ak ≥ a2k+2 (ak lớn nhất trong 3 phần tử)
Đặc tính:
a0 là phần tử lớn nhất
Heap chưa chắc có thứ tự
Nửa sau của mảng bất kỳ thỏa định nghĩa heap
Heap sort:
Lấy a0 ra, tái tạo lại heap => Phần tử lớn nhất
Lấy a0 mới ra, tái tạo lại heap => Phần tử lớn kề
…
Heap Sort
void HeapSort(int a[], int n){
//xây dựng heap ban đâu
BuildHeap(a,n); //mảng đã là một heap
for(int i=n-1; i>=1; i--){
int current = a[i];
a[i]= a[0]; //chuyển phần tử lớn nhất về cuối
//a[1..i-1] đang là heap, thêm current vào để
vẫn là heap
InsertHeap(current,a,0,i-1);
}
}
Biểu diễn Heap
Dạng cây nhị phân:
Node gốc là a0
2 node con của phần tử
ak là 2 phần tử a2k+1 và
a2k+2
Ở mức cuối cùng, các
node lấp đầy từ bên trái
sang bên phải (cây nhị
phân gần đầy đủ)
0 1 2 3 4 5 6 7 8
Ví dụ Heap Sort
y
r p
d f b k
current
a c
0
y 1
r 2
p 3
d 4
f 5
b 6
k 7
a 8
c
Ví dụ Heap Sort
r
f p
d c b k
current
a y
0
r 1
f 2
p 3
d 4
c 5
b 6
k 7
a 8
y
Ví dụ Heap Sort
p
f k
d c b a
current
r y
0
p 1
f 2
k 3
d 4
c 5
b 6
a 7
r 8
y
Ví dụ Heap Sort
k
f b
d c a p
current
r y
0
k 1
f 2
b 3
d 4
c 5
a 6
p 7
r 8
y
Ví dụ Heap Sort
f
d b
a c k p
current
r y
0
f 1
d 2
b 3
a 4
c 5
k 6
p 7
r 8
y
Ví dụ Heap Sort
d
c b
a f k p
current
r y
0
d 1
c 2
b 3
a 4
f 5
k 6
p 7
r 8
y
Ví dụ Heap Sort
c
a b
d f k p
current
r y
0
c 1
a 2
b 3
d 4
f 5
k 6
p 7
r 8
y
Ví dụ Heap Sort
b
a c
d f k p
current
r y
0
b 1
a 2
c 3
d 4
f 5
k 6
p 7
r 8
y
Giải thuật tái tạo lại Heap
Algorithm InsertHeap
Input: mảng là heap trong khoảng từ low+1 đến high, current là giá trị
cần thêm vào
Output: mảng là heap trong khoảng từ low đến high
1. Bắt đầu kiểm tra tại vị trí low
2. while (chưa kiểm tra xong đến high)
2.1. Tìm lớn nhất trong bộ ba phần tử current, a[2k+1], a[2k+2]
2.2. if (phần tử đó là current)
2.2.1. Ngừng vòng lặp
2.3. else
2.3.1. Dời phần tử lớn nhất lên vị trí hiện tại
2.3.2. Kiểm tra bắt đầu từ vị trí của phần tử lớn nhất này
3. Đưa current vào vị trí đang kiểm tra
End
Giải thuật tái tạo Heap
Input: InsertHeap(current, a[], low, high)
Mảng a[low+1…high] đã là một heap
Output: thêm current vào sao cho mảng a[low…high]
vẫn là một heap
void InsertHeap(int current,int a[], int low, int high)
{
int large = 2*low +1;
while(large <=high){//chưa xét hết phần tử
if(large
if(a[large +1]>a[large])large++;
if(current>=a[large])break;
a[low]=a[large]; //di chuyển phần tử max
low = large;
large = 2*low +1;
}
a[low]=current; //chuyển current vào vị trí đang xét
}
Xây dựng Heap ban đầu
void BuildHeap(int a[],int n){
//nửa sau từ n/2 --> n-1 đã là một heap
for(int i=n/2-1; i>=0; i--){
int current = a[i];
InsertHeap(current,a,i,n-1);
}
}
Ví dụ xây dựng Heap ban đầu
0
p 1
c 2
y 3
d 4
f 5
b 6
k 7
a 8
r Bước 1
0
p
1
c
2
y
3
r
4
f
5
b
6
k
7
a
8
d
0
p 1
c 2
y 3
r 4
f 5
b 6
k 7
a 8
d Bước 2
Bước 3
0
p
1
r
2
y
3
d
4
f
5
b
6
k
7
a
8
c
0
p 1
r 2
y 3
c 4
f 5
b 6
k 7
a 8
d Bước 3’
Bước 4
0
y 1
r 2
p 3
d 4
f 5
b 6
k 7
a 8
c
Đánh giá Heap Sort
Trường hợp xấu nhất và trung bình:
C = 2n lg n + O(n)
M = n lg n + O(n)
So với Quick Sort
Trung bình: chậm hơn quick sort
Xấu nhất: O(n lg n) < n(n-1)/2
Radix Sort
Radix sort khác với các phương pháp sắp xếp khác.
Radix sort
Xem các phần tử như các chuỗi
Nhóm các phần tử có cùng kí tự tận cùng phải
Nhập các nhóm lại với nhau
Lập lại bước trên cho tất cả các vị trí từ vị trí tận cùng
phải (rightmost) cho đến vị trí tận cùng trái (leftmost)
Radix Sort – Ví dụ
mom, dad, god, fat, bad, cat, mad, pat, bar, him original list
(dad,god,bad,mad) (mom,him) (bar) (fat,cat,pat) group strings by
rightmost letter
combine groups
combine groups
dad,god,bad,mad,mom,him,bar,fat,cat,pat
(dad,bad,mad,bar,fat,cat,pat) (him) (god,mom) group strings by middle letter
dad,bad,mad,bar,fat,cat,pat,him,god,mom
(bad,bar) (cat) (dad) (fat) (god) (him) (mad,mom) (pat) group strings by first
letter
bad,bar,cat,dad,fat,god,him,mad,mom,par combine groups
(SORTED)
Radix Sort – Ví dụ
Radix Sort - Algorithm
void RadixSort(inout theArray:ItemArray, in n:integer, in
d:integer)
// sort n d-digit integers in the array theArray
for (j=d; j>=1; j--) {
Khởi tạo 10 nhóm bằng rỗng
Khởi tạo các counter của các nhóm bằng 0
for (i=0; i
k = chữ số thứ j của theArray[i]
Đặt theArrar[i] vào nhóm thứ k
Tăng counter thứ k thêm 1
}
Thay thế các phần tử trong theArray bởi các phần tử
trong nhóm 1, nhóm 2,… theo thứ tự
}
Đánh giá Radix Sort
Đòi hỏi 2*n*d phép gán để sắp n chuỗi có chiều dài là d
Độ phức tạp O(n)
So sánh các giải thuật
Luyện tập
Trình bày cách thực hiện sắp xếp mảng sau theo
các thuật toán (ghi kết quả sau từng bước)
Selection Sort
Insertion Sort
Buble Sort
Merge Sort
Quick Sort
A={10, 3, 7, 6, 2, 5, 4, 16, 20, 1 }