# Chuyên đề Sắp xếp (Sorting)
Viết bởi: Nguyễn Thế Ngọc Hà
Chuẩn bị bởi: Nguyễn Thế Ngọc Hà và Trần Bá Anh Hào
## Sắp xếp trộn (Merge Sort)
### Ý tưởng
Hoạt động theo kiểu đệ quy:
- Chia dữ liệu làm 2 phần.
- Sắp xếp 2 phần đó bằng kĩ thuật 2 con trỏ (2 pointer).
### Ưu điểm
- Chạy nhanh, độ phức tạp $O(NlogN)$.
- Ổn định
### Nhược điểm
- Cần dùng thêm bộ nhớ để tạo một mảng để lưu.
### Mô phỏng
https://visualgo.net/en/sorting
### Cài đặt
```cpp
// Sắp xếp các phần tử có chỉ số từ left đến right của mảng data.
void mergesort(int data[MAX], int left, int right) {
if (data.length == 1) {
// Dãy chỉ gồm 1 phần tử, ta không cần sắp xếp.
return ;
}
int mid = (left + right) / 2;
// Sắp xếp 2 phần
mergesort(data, left, mid);
mergesort(data, mid+1, right);
// Trộn 2 phần đã sắp xếp lại
int i = left, j = mid + 1; // phần tử đang xét của mỗi nửa
int cur = 0; // chỉ số trên mảng a
while (i <= mid || j <= right) { // chừng nào còn 1 phần chưa hết phần tử.
if (i > mid) {
// bên trái không còn phần tử nào
a[cur++] = data[j++];
} else if (j > right) {
// bên phải không còn phần tử nào
a[cur++] = data[i++];
} else if (data[i] < data[j]) {
// phần tử bên trái nhỏ hơn
a[cur++] = data[i++];
} else {
a[cur++] = data[j++];
}
}
// copy mảng a về mảng data
for (int i = 0; i < cur; i++)
data[left + i] = a[i];
}
```
## Sắp xếp chọn (Selection Sort)
### Ý tưởng
Lần lượt chọn ra các phần tử nhỏ nhất trong dãy để đưa nó về đúng vị trí.
### Ưu điểm
Dễ cài đặt, ngắn.
### Nhược điểm
Chạy rất lâu với dữ liệu lớn, độ phức tạp $O(N^2)$.
### Mô phỏng
https://visualgo.net/en/sorting
### Cài đặt
```cpp
int mn,idx;
for (int i=0;i<n;i++){
mn=a[i];
idx=i;
for (int j=i;j<n;j++){
if (mn>a[j]){
//Lưu chỉ số của phần tử nhỏ nhất vừa tìm
mn=a[j];
idx=j;
}
}
swap(a[idx],a[i]); //Tráo đổi vị trí với phần tử thứ i
}
```
## Sắp xếp đếm phân phối (Counting Sort)
### Ý tưởng
Các phần tử được lưu giữ trong một mảng từ $1$ đến $c$ và $c = O(N)$. Chỉ số của mảng phụ chính là các phần tử ở mạng cần sắp xếp còn giá trị các phần tử thể hiện cho số lần xuất hiện của phần tử ấy.
### Ưu điểm
Chạy rất nhanh, trong 1 số trường hợp mà các phần tử trong mảng không phân cách quá lớn thì thuật toán này là nhanh nhất.
### Nhược điểm
Sử dụng nhiều bộ nhớ.
### Cài đặt
```cpp
for (int i=0;i<n;i++){
d[a[i]]++;
mx=max(a[i],mx);
}
for(int i=0;i<=mx;i++){
while (d[i]!=0){
cout<<i<<" ";
i--;
}
}
```