You are on page 1of 11

THUẬT TOÁN SẮP XẾP

- Selection sort
+ Ý tưởng
 Tạ i mỗ i lượ t, chọ n phầ n tử nhỏ nhấ t trong số cá c phầ n tử chưa đượ c sắ p. Đưa
phầ n tử đượ c chọ n và o vị trí đú ng bằ ng phép đổ i chỗ . z
 Sau lượ t thứ i (i = 1..n-1) , dã y cầ n sắ p coi như đượ c chia thà nh 2 phầ n – Phầ n
đã sắ p: từ vị trí 1 đến i – Phầ n chưa sắ p: từ vị trí i +1 đến n

+ Code
void SelectionSort(int a[], int n) {
int min;
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;
}
if (a[min] < a[i])swap(a[min], a[i]);
}
}

+ Đánh giá độ phức tạp thuật toán Selection Sort


 Trườ ng hợ p tố t: O(n2)
 Trườ ng hợ p trung bình: O(n2)
 Trườ ng hợ p xấ u: O(n2)
 Khô ng gian sử dung: O(1)

- Insertion sort

+ Ý tưởng
 Dã y cầ n sắ p đượ c chia thà nh 2 phầ n: mộ t là phầ n đã sắ p, cò n lạ i là phầ n chưa
sắ p
 Tạ i mỗ i lượ t, phầ n tử đầ u tiên trong phầ n chưa sắ p sẽ đượ c “thêm” và o đú ng
vị trí củ a nó trong phầ n đã sắ p.

1|Page
+ Code
void InsertionSort(int a[], int n) {
int saved;
for (int i = 1; i < n; i++) {
saved = a[i];
int j = i;

/* Xét từ phần tử hiện tại trở về trước.


Phần tử nào có phần tử trước đó > giá trị đang xét thì dồn lên. */
for (; j > 0 && saved < a[j - 1]; j--) {
a[j] = a[j - 1];
}
/* Chèn giá trị đang xét tại vị trí mà phần tử trước đó
không còn lớn hơn nó nữa. */
a[j] = saved;
}
}

+ Đánh giá độ phức tạp thuật toán Insertion Sort


 Trườ ng hợ p tố t: O(n)
 Trườ ng hợ p trung bình: O(n2)
 Trườ ng hợ p xấ u: O(n2)
 Khô ng gian sử dung: O(1)
- Bubble sort
+ Ý tưởng
 Dã y cầ n sắ p đượ c chia thà nh 2 phầ n: mộ t là phầ n đã sắ p, cò n lạ i là phầ n chưa
sắ p
 Thô ng qua phép đổ i chỗ , tạ i mỗ i lượ t phầ n tử nhỏ nhấ t trong phầ n chưa đượ c
sắ p sẽ đượ c “đẩ y dầ n” lên trướ c và cuố i cù ng nhậ p và o phầ n đượ c sắ p.

2|Page
+ Code
void BubbleSort(int a[], int n) {
for (int i = 1; i < n - 1; i++) {
for (int j = n - 1; j >= i + 1; j--) {
if (a[j] < a[j - 1])swap(a[j], a[j - 1]);
}
}
}

+ Đánh giá độ phức tạp thuật toán Bubble Sort


 Trườ ng hợ p tố t: O(n2)
 Trườ ng hợ p trung bình: O(n2)
 Trườ ng hợ p xấ u: O(n2)
 Khô ng gian sử dung: O(1)

- Shell sort
+ Ý tưởng

Shell sort lấ y ý tưở ng chính từ Insert sort. Shell sort hoạ t độ ng bằ ng cá ch sắ p xếp cá c
phầ n tử nằ m xa nhau, sau đó dầ n rú t ngắ n khoả ng cá ch sắ p xếp(gap), đều nà y giú p di
chuyển cá c phầ n tử đi mộ t khoả ng cá ch xa có thể giú p cá c phầ n tử đi về vị trí chính
xá c củ a mình hiệu quả hơn so vớ i việc di chuyển qua từ ng phầ n tử liền kề. 

+ Code
void ShellSort(int a[], int n) {
int saved;
for (int interval = n / 2; interval > 0; interval /= 2) {
for (int i = interval; i < n; i += 1) {
int j = i;
saved = a[i];
for (; j >= interval && a[j - interval] > saved; j -= interval) {
a[j] = a[j - interval];
}
a[j] = saved;
}
}
}

+ Đánh giá độ phức tạp thuật toán Shell sort


 Trườ ng hợ p tố t: O(nlog(n))

3|Page
 Trườ ng hợ p trung bình: O(nlog(n))
 Trườ ng hợ p xấ u: O(n2)
 Khô ng gian sử dung: O(1)
- Merge sort
+ Ý tưởng
Bao gồ m 3 bướ c
 Chia: Phâ n chia dã y cầ n đượ c sắ p S gồ m n phầ n tử thà nh 2 dã y con vớ i số
phầ n tử là n/2 S1 và S2
 Trị: Lầ n lượ t sắ p xếp hai dã y con S1 và S2 bằ ng sắ p xếp kiểu hò a nhậ p
 Tổ hợ p: Nhậ p 2 dã y con đã đượ c sắ p S1 và S2 thà nh mộ t dã y duy nhấ t

+ Code
void Merge(int A[], int l, int mid, int r) {
int* tempA = new int[r-l+1];
int l1 = l; int r1 = mid;
int l2 = mid + 1; int r2 = r; int i = l;
for (; i<=r; ++i) {
if (l1 > r1 && l2 <= r2) tempA[i] = A[l2++];
else if (l2 > r2 && l1 <= r1) tempA[i] = A[l1++];
else
tempA[i] = (A[l1] < A[l2]) ? A[l1++] : A[l2++];
}
for (i = l; i <= r; ++i)
A[i] = tempA[i];
delete[] tempA;
}

void MergeSort(int A[], int l, int r)


{
if (l < r)
{ // chia thành hai dãy con
int mid = (l + r) / 2; // chỉ số điểm giữa
// sắp xếp dãy con trái A[first..mid]
MergeSort(A, l, mid);
// sắp xếp dãy con phải A[mid+1..last]
MergeSort(A, mid + 1, r);
// Trộn hai dãy con
Merge(A, l, mid, r);
}
}

+ Đánh giá độ phức tạp thuật toán Merge Sort


 Trườ ng hợ p tố t: O(nlog(n))

4|Page
 Trườ ng hợ p trung bình: O(nlog(n))
 Trườ ng hợ p xấ u: O(nlog(n))
 Khô ng gian sử dụ ng: O(n)
- Quick sort
+ Ý tưởng
 Chia – Pha phâ n đoạ n : Chọ n mộ t phầ n tử trong dã y là m phầ n tử chố t p . Chia dã y
đã cho thà nh 3 nhó m : <p ,p,>p . p thườ ng đượ c chọ n là : vị trí đầ u, vị trí giữ a, vị
trí cuố i.
 Trị: Sắ p xếp đượ c tiếp tụ c mộ t cá ch đệ qui vớ i nhó m thứ 1 và nhó m thứ 3.

+ Code
int PartitionL(int A[], int l, int r) {
int x = A[l];
int j = r + 1;
int i = l;
while (i < j) {
i++;
while ((i <= r) && (A[i] < x)) i++;
j--;
while ((j >= l) && (A[j] > x)) j--;
swap(A[i], A[j]);
}
swap(A[i], A[j]);
swap(A[j], A[l]);
return j;
}

int PartitionR(int A[], int l, int r) {


int x = A[r];
int j = l - 1;
for (int i = l; i < r; i++) {
if (x >= A[i]) {
j++;
swap(A[i], A[j]);
}
}
swap(A[j + 1], A[r]);
return (j + 1);
}

void QuickSort(int A[], int l, int r) {


if (l < r) {
int p = PartitionL(A, l, r);
if(l<p) QuickSort(A, l, p-1);
if(r>p) QuickSort(A, p + 1, r);
}
}

5|Page
void QuickSortMid(int A[], int l, int r) {
int i = l, j = r;
int x = A[(l + r) / 2];
while (i <= j) {
while (A[i] < x)i++;
while (A[j] > x)j--;
if (i <= j) {
if (i < j) {
swap(A[i], A[j]);
}
i++;
j--;
}
}
if (l < j)QuickSortMid(A, l, j);
if (i < r)QuickSortMid(A, i, r);
}

+ Đánh giá độ phức tạp thuật toán Quick Sort


 Trườ ng hợ p tố t: O(nlog(n))
 Trườ ng hợ p trung bình: O(nlog(n))
 Trườ ng hợ p xấ u: O(n2)
 Khô ng gian sử dụ ng: O(log(n))
- Heap sort (Sắp xếp kiểu vun đống)
+ Ý tưởng
Cấ u trú c Đố ng – Đố ng là mộ t câ y nhị phâ n có hai tính chấ t.
 Là câ y nhị phâ n hoà n chỉnh
 Có thứ tự : mỗ i nú t đượ c gắ n vớ i mộ t giá trị số tự nhiên, sao cho giá trị củ a
nú t cha bao giờ cũ ng lớ n hơn giá trị củ a nú t con (Max Heap)
 Đố ng đượ c lưu trữ trong má y tính dướ i dạ ng mộ t vector lưu trữ
 Ta coi dã y cầ n sắ p xếp là mộ t câ y nhị phâ n hoà n chỉnh, sau đó hiệu chỉnh câ y
thà nh dạ ng cấ u trú c heap ( vun đố ng)
 Dự a và o tính chấ t củ a cấ u trú c heap, ta có thể lấ y đượ c ra phầ n từ lớ n nhấ t
hoặ c nhỏ nhấ t củ a dã y, phầ n tử nà y chính là gố c củ a heap. Giả m số lượ ng
phầ n tử củ a câ y nhị phâ n và tá i cấ u trú c heap.
 Đưa phầ n tử đỉnh heap về đú ng vị trí củ a dã y ở cuố i mả ng, sau đó giả m số
lượ ng phầ n tử củ a mả ng (khô ng xét tớ i phầ n tử cuố i nữ a)
 Tá i cấ u trú c heap và lặ p lạ i việc lấ y phầ n tử gố c củ a cấ u trú c heap cho tớ i khi
danh sá ch ban đầ u chỉ cò n 1 phầ n tử . Đưa phầ n tử nà y về đú ng vị trí và kết
thú c thuậ t toá n.
Ta phả i thự c hiện tá i cấ u trú c heap, vun lạ i đố ng bở i vì sau khi lấ y ra phầ n tử gố c heap,
cấ u trú c heap khô ng cò n nữ a.

6|Page
+ Code
void Heapify(int a[], int n, int i) {
int largest = i;
int l = 2 * i + 1, r = 2 * i + 2;
if (l < n && a[l] > a[largest]) largest = l;
if (r < n && a[r] > a[largest]) largest = r;
if (largest != i) {
swap(a[i], a[largest]);
Heapify(a, n, largest);
}
}

void HeapSort(int a[], int n) {


for (int i = (n / 2) - 1; i >= 0; i--) {
Heapify(a, n, i);
}
for (int j = n - 1; j > 0; j--) {
swap(a[j], a[0]);
Heapify(a, j, 0);
}
}

+ Đánh giá độ phức tạp thuật toán Heap Sort


 Trườ ng hợ p tố t: O(nlog(n))
 Trườ ng hợ p trung bình: O(nlog(n))
 Trườ ng hợ p xấ u: O(nlog(n))
 Khô ng gian sử dụ ng: O(1)
- Counting sort
+ Ý tưởng
Bước 1:

Trong bướ c đầ u tiên, chú ng tô i đếm số lầ n xuấ t hiện củ a từ ng phầ n tử trong mả ng cầ n


sắ p xếp A. Kết quả đượ c lưu và o mả ng C.

7|Page
Bước 2: Ở bướ c nà y, chú ng ta cầ n xem xét sử a đổ i giá trị củ a C. C[i] thể hiện giớ i hạ n
trên củ a chỉ số củ a phầ n tử  i sau khi sắ p xếp.

Bước 3: Duyệt qua từ ng phầ n tử củ a A và đặ t nó và o đú ng chỉ số củ a mả ng chứ a cá c giá


trị đã sắ p xếp B dự a và o C.

8|Page
+ Code
void CountingSort(int a[], int n) {
int max = a[0], min = a[0];
int *result = new int[n];
// tìm max min của mảng
for (int i = 1; i < n; i++) {
if (a[i] > max)max = a[i];
if (a[i] < min)min = a[i];
}
int k = max - min + 1; // k là độ dài của mảng count_array
int* count_array = new int[k];
//khởi tạo các giá trị của mảng count_array là 0
for (int j = 0; j < k; j++) count_array[j] = 0;
//Đếm số lượng các phần tử phân biệt của mảng
for (int z = 0; z < n; z++)count_array[a[z] - min]++;
/* Thay đổi giá trị của count_array[p] thể hiện giới hạn trên
của chỉ số của phần tử p sau khi sắp xếp */
for (int p = 1; p < k; p++) count_array[p] += count_array[p - 1];
/* Duyệt qua từng phần tử của a và đặt nó vào đúng chỉ số của mảng
chứa các giá trị đã sắp xếp result dựa vào count_array. */
for (int q = 0; q < n; q++) {
result[count_array[a[q] - min] - 1] = a[q];
count_array[a[q] - min]--;
}
// Sao chép mảng result vào mảng a.
for (int t = 0; t < n; t++) a[t] = result[t];
delete[] result;
delete[] count_array;
}

+ Đánh giá độ phức tạp thuật toán Counting Sort


 Trườ ng hợ p tố t: O(n+k)
 Trườ ng hợ p trung bình: O(n+k)
 Trườ ng hợ p xấ u: O(n+k)

9|Page
 Khô ng gian sử dụ ng: O(max)
- Radix Sort
+ Ý tưởng
Dự a trên nguyên tắ c phâ n loạ i thư củ a bưu điện. Nó khô ng hề quan tâ m đến việc so
sá nh giá trị củ a phầ n tử và bả n thâ n việc phâ n loạ i và trình tự phâ n loạ i sẽ tạ o ra thứ tự
cho cá c phầ n tử .

+ Code
int max_array(int a[], int n) {
int max = a[0];
for (int i = 1; i < n; i++) if (a[i] > max)max = a[i];
return max;
}

void countingsort(int a[], int n, int place) {


int* result = new int[n];
int max = (a[0] / place) % 10;
for (int i = 1; i < n; i++) {
if (((a[i] / place) % 10) > max)max = (a[i] / place) % 10;
}
int* count = new int[max + 1];
for (int j = 0; j <= max; j++)count[j] = 0;
for (int z = 0; z < n; z++)count[(a[z] / place) % 10]++;
for (int p = 1; p < 10; p++)count[p] += count[p - 1];

for (int q = n-1; q >= 0; q--) {


result[count[(a[q] / place) % 10] - 1] = a[q];
count[(a[q] / place) % 10]--;
}

for (int t = 0; t < n; t++) {


a[t] = result[t];
}

10 | P a g e
delete[] result;
delete[] count;
}

void RadixSort(int a[], int n) {


int max = max_array(a, n);
for (int place = 1; (max / place) > 0; place *= 10) {
countingsort(a, n, place);
}
}

+ Đánh giá độ phức tạp thuật toán Radix Sort


 Trườ ng hợ p tố t: O(nk)
 Trườ ng hợ p trung bình: O(nk)
 Trườ ng hợ p xấ u: O(nk)
 Khô ng gian sử dụ ng: O(n+k)

11 | P a g e

You might also like