You are on page 1of 6

SẮP XẾP NHANH (QUICK SORT)

1 – SẮP XẾP NHANH (QUICK SORT) LÀ GÌ ?

Thuật toán Quick Sort (Sắp xếp nhanh) là một quy trình có hệ
thống để sắp xếp các phần tử của một mảng. Giống như Merge
Sort, QuickSort là một thuật toán sử dụng cách thức chia để trị
(Divide and Conquer algorithm).
Tên gọi “Quick Sort” ám chỉ thuật toán này có khả năng sắp xếp
dữ liệu nhanh hơn nhiều so với bất kỳ thuật toán sắp xếp truyền
thống nào khác. Tuy nhiên, Quick Sort không được ổn định vì thứ
tự tương đối của các phần tử bằng nhau không được đảm bảo.

2 - ĐỘ PHỨC TẠP

Tốt nhất : O( n log n)


Trung bình : O( n log n)
Xấu nhất : O( n²)
Bộ nhớ : O( log n)
Stable : Có / Không

3 - ƯU ĐIỂM

 Thuật toán có độ phức tạp nhỏ hơn các thuật toán sắp
xếp đơn giản, tốc độ xử lý tương đối nhanh. Trong một số
trường hợp, quicksort là thuật toán có tốc độ tốt nhất
 Thông dụng, được áp dụng nhiều trong lập trình, trong thư
viện của các ngôn ngữ lập trình như C++, Java, C# . . .
 Có thể ứng dụng vào xử lý dữ liệu lớn.
4 – NHƯỢC ĐIỂM

 Thuật toán không có tính ổn định, không có tính thích ứng,


dễ ảnh hưởng bởi dữ liệu đầu vào
 Tốn không gian bộ nhớ hơn so với các thuật toán sắp xếp
đơn giản
 Tư tưởng và giải thuật khá phức tạp
 Khó khăn trong việc lựa chọn phần tử làm chốt trong phân
hoạch. Việc lựa chọn có thể ảnh hưởng rất nhiều đến hiệu
suất của thuật toán tuy nhiên ta không thế đưa ra lựa
chọn tối ưu nhất.
 không hiệu quả trên những dãy đã được sắp xếp sẵn. Khi
đó ta phải mất N lần gọi đệ quy và mỗi lần chỉ loại được 1
phần tử. Thời gian thực hiện thuật toán trong trường hợp
xấu nhất này là O(n2).

5 – Ý TƯỞNG

Thuật toán sẽ có hai giai đoạn. Giai đoạn đầu là phân đoạn mảng
(partition()) và giai đoạn sau là sắp xếp (quickSort()).
 Chọn pivot cho mảng.
 Tạo hai biến là left và right để trỏ đến bên trái và bên phải của
danh sách.
 Tiến hành so sánh các phần tử với pivot. Trong trường hợp phần
tử nhỏ hơn pivot thì dịch chuyển qua bên trái và ngược lại.
 Sau khi đã dịch chuyển thì tiến hành công việc sắp xếp các phần
tử trong mảng con mới, trước khi tiếp tục phân đoạn tiếp theo.
6 - ĐIỂM QUAN TRỌNG

Các nhiều phiên bản Quick Sort khác nhau chọn pivot theo những
cách khác nhau. Tốc độ sắp xếp của thuật toán phải phụ thuộc
vào việc lựa chọn pivot, có một số cách để chọn như sau:
 Luôn chọn phần tử đầu tiên làm pivot.
 Luôn chọn phần tử cuối cùng làm pivot
 Chọn một phần tử ngẫu nhiên làm pivot.
 Chọn vị trí ở giữa làm pivot.
 Sử dụng phương pháp median-of-3 *

Phần tử được chọn làm chốt tối ưu nhất là phần tử trung vị, phần
tử này làm cho số phần tử nhỏ hơn trong dãy bằng hoặc sấp xỉ
số phần tử lớn hơn trong dãy. Tuy nhiên, việc tìm phần tử này rất
tốn kém, phải có thuật toán tìm riêng, từ đó làm giảm hiệu suất
của thuật toán tìm kiếm nhanh, do đó, để đơn giản, người ta
thường sử dụng phần tử chính giữa làm chốt.

* Phương pháp này nghĩa là trong quá trình chọn pivot, chúng ta
sẽ lấy phần tử đầu tiên, phần tử ở giữa và phần tử cuối cùng của
dãy sau đó chọn ra trung vị của 3 phần tử này để làm pivot. Tuy
nhiên, vẫn tồn tại 1 số dãy mà phương pháp median-of-3 cho độ
phức tạp O(n2), những dãy như vậy được gọi là "median-of-3
killer".
7 - GIẢI THUẬT
void Partition(int A[], int left, int right)
{
// Kiểm tra xem nếu mảng có 1 phần tử thì không
cần sắp xếp
if (left >= right) return;

int pivot = A[(left + right) / 2]; // Chọn


phần tử chính giữa dãy làm chốt

// i là vị trí đầu và j là cuối đoạn


int i = left, j = right;
while (i < j)
{
while (A[i] < pivot) i++;
// Nếu phần tử bên trái nhỏ hơn pivot thì ok, bỏ
qua
while (A[j] > pivot) j--;
// Nếu phần tử bên phải nhỏ hơn pivot thì ok, bỏ
qua

// Sau khi kết thúc hai vòng while ở trên thì


chắc chắn
// vị trí A[i] phải lớn hơn pivot và A[j] phải
nhỏ hơn pivot
// nếu i < j
if (i <= j)
{
if (i < j) // nếu i != j (tức không
trùng thì mới cần hoán đổi)
swap(A[i], A[j]); // Thực hiện
đổi chổ ta được A[i] < pivot và A[j] > pivot
i++;
j--;
}
}

// Gọi đệ quy sắp xếp dãy bên trái pivot


Partition(A, left, j);
// Gọi đệ quy sắp xếp dãy bên phải pivot
Partition(A, i, right);
}

// Hàm sắp xếp chính


void QuickSort(int A[], int n)
{
Partition(A, 0, n - 1);
}
8 - BÀI TẬP ÁP DỤNG

You might also like