---
# System prepended metadata

title: Chuyên đề Sắp xếp (Sorting)

---

# 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--;
    }
}
```