Sorting

Sorting Algorithm

02/11/2019

This post is going to give you some interesting algorithm ralating sorting elements.

Problem Sorting an array $a$ consists of $n$ elements in increasing order.

I. $O(n^2)$ Algorithm

1. Interchange Sort

1for(int i=0; i<n; i++){
2    for(int j=i+1; j<n; j++){
3        if (a[j] < a[i]) swap(a[j], a[i]);
4    }
5}

2. Bubble Sort

Từng phần tử nổi lên như bong bóng vậy đó.

1for(int i=n-1; i>0; i--){
2	    for(int j=1; j<=i; j++){
3	        if (a[j] < a[j-1]) swap(a[j], a[j-1]);
4	    }
5	}

Ngoài ra còn có Insertion Sort, Selection Sort, Shaker Sort.

II. $O(n\ log(n))$ Algorithm

1. Quick Sort

Ý tưởng

  • Chọn 1 phần tử cần sort (pivot)
  • Sort phần tử đó: partition
  • Quick sort cho 2 bên pivot

Cài đặt
Tham khảo GFG, chọn phần tử cuối làm pivot cho dễ cài đặt.

 1int partition(int l, int r);
 2void quick_sort(int l, int r){
 3    if (l >= r) return;
 4    pi = partition(l, r);  //correct pos of pivot
 5    quick_sort(l, pi-1);
 6    quick_sort(pi+1, r);
 7}
 8int partition(int l, int r){
 9    int pivot = a[r];
10    int pivot_index = l;
11    for(int i=l; i<=r-1; i++){
12        if (a[i] < pivot){
13            swap(a[i], a[pivot_index]);
14            pivot_index++;
15        }
16    }
17    swap(a[pivot_index], a[r]);
18    return i;
19}

Lưu ý
Quick Sort có độ phức tạp trung bình là $O(n\ log(n))$ và worst case là $O(n^2)$ khi mảng đã được sort (kể cả tăng hay giảm).

2. Merge Sort

Ý tưởng

  • Chia mảng thành 2 phần left, right
  • Sort bên trái, Sort bên phải
  • Merge 2 bên lại.

Ý tưởng divide and conquer (DP), thao tác chính là thao tác merge đó mới chính là lúc sort thực sự.

Cài đặt Tham khảo GFG

 1//a[] là biến toàn cục rồi
 2void merge(int l, int m, int r);
 3void merge_sort(int l, int r){
 4    if (l >= r) return; //= is maximal roi
 5    int m = (l+r)/2;
 6    merge_sort(l, m);
 7    merge_sort(m+1, r);
 8    merge(l, m, r);
 9}
10void merge(int l, int m, int r){
11    int n1 = m-l+1;
12    int n2 = r-m;
13    int L[n1], R[n2]; //temp
14    for(int i=0; i<n1; i++){
15        L[i] = a[l+i];
16    }
17    for(int i=0; i<n2; i++){
18        R[i] = a[m+1+i];
19    }
20    int i = 0, j = 0, k = l;
21    while(i<n1 && j<n2){
22        if (L[i] <= R[j]) a[k++] = L[i++];
23        else a[k++] = R[j++];
24    }
25    while(i<n1)
26        a[k++] = L[i++];
27    while(j<n2) 
28        a[k++] = R[j++];
29}

$\rightarrow$ Merge Sort luôn có độ phức tạp $O(n\ log(n))$.

III. O(n) Algorithm

1. Counting Sort

Khi mà mảng chỉ gồm các small elements thì ta có thể dùng Counting Sort.
Ý tưởng
Nếu phần tử $x$ trước nó có $y$ phần tử nhỏ hơn thì nó phải nằm ở vị trí $y$ (based 0).
Cài đặt

 1int cnt[M]; //M = *max_element(a, a+n)
 2memset(cnt, 0, sizeof cnt);
 3for(int i=0; i<n; i++){
 4    cnt[a[i]]++;
 5}
 6for(int i=1; i<M; i++){
 7    cnt[i] += cnt[i-1];
 8}
 9int ans[n];
10for(int i=0; i<n; i++){
11    ans[--cnt[a[i]]] = a[i];  //base 0
12}
13for(int i=0; i<n; i++) a[i] = ans[i]; //copy answer

Còn 1 số thuật toán fast khác như Radix Sort, Flash Sort.