LATEST

Thuật toán sắp xếp Quick Sort trong C / C++

Trong bài viết này, codehow sẽ giới thiệu đến các bạn thuật toán sắp xếp Quick Sort trong C / C++. Đây là thuật toán sắp xếp nhanh nhất trong tất cả các thuật toán mình đã giới thiệu trước đây.

Vì sao nó được xem là thuật toán sắp xếp nhanh nhất thì các bạn hãy xem đến cuối bài viết nhé. Còn bây giờ, mình sẽ đưa ra khái niệm về sắp xếp nhanh Quick Sort là gì? và cách thức nó hoạt động ra sao.

Sắp xếp Quick Sort là gì? Cách thức nó hoạt động

Thuật toán sắp xếp Quick Sort (hay còn gọi là sắp xếp nhanh) sử dụng phương pháp chia để trị (divide and conquer).

Chúng ta cũng có một thuật toán áp dụng phương pháp này đó là thuật toán sắp xếp trộn (Merge Sort) tuy nhiên thuật toán Quick Sort tối ưu hơn nhiều.

Về cách thức nó hoạt động như sau:

  • Thuật toán sẽ chọn một phần tử trong mảng làm điểm đánh dấu (pivot).
  • Sau khi chọn phần tử đánh dấu, ta tiến hành chia mảng thành hai nửa bằng cách so sánh với phần tử đánh dấu.
  • Một nửa bao gồm các phần tử nhỏ hơn pivot và một nửa gồm các phần tử lớn hơn pivot.

*Lưu ý: Tốc độ sắp xếp của thuật toán dựa vào việc lựa chọn phần tử pivot, có một số cách chọn như sau:

  • Chọn pivot là phần tử đầu tiên của mảng.
  • Chọn pivot là phần tử giữa mảng.
  • Chọn pivot là phần tử cuối mảng.
  • Chọn pivot là một phần tử ngẫu nhiên trong mảng.

Tùy thuộc vào bài toán mà chúng ta chọn phần tử pivot nhé.

Hãy cùng xem ví dụ minh họa dưới đây để hiểu rõ hơn nhé, trong ví dụ này mình chọn cách xác định phần tử pivot là chọn phần tử cuối cùng trong mảng.

bai15 01 png

Giả sử mình có một mảng Number = {9, -3, 5, 2, 6, 8, -6, 1, 3} như hình trên. Phần tử pivot mình chọn phần tử cuối cùng nên sẽ là số 3.

Tiến hành so sánh với giá trị 3 để chia thành hai mảng con. Mảng thứ nhất là {-3, 2, -6, 1} là các phần tử nhỏ hơn hoặc bằng 3. Mảng thứ hai là {8, 5, 9, 6} là các phần tử lớn hơn hoặc bằng 3.

Tiếp tục chọn phần tử cuối cùng của hai mảng con vừa chia làm phần tử đánh dấu pivot. Chia thành hai mảng con bằng cách so sánh với phần tử pivot vừa xác định.

Cứ như vậy cho đến khi kết thúc vòng lặp, ta sẽ được một mảng đã sắp xếp Number = {-6, -3, 1, 2, 5, 6, 8, 9}.

Thuật toán sắp xếp Quick Sort trong C / C++

Thuật toán sắp xếp Quick Sort trong C / C++ được chia thành hai giai đoạn. Giai đoạn thứ nhất là giai đoạn phân mảng và giai đoạn hai là giai đoạn sắp xếp. Vì vậy mình sẽ tạo hai hàm riêng biệt để xử lý việc này đó là: partition()quickSort().

Ngoài ta chúng ta cần có thêm hàm Swap() để hoán đổi hai vị trí trong giai đoạn phân mảng.

Hàm partition():

int partition (int arr[], int low, int high)
{
    int pivot = arr[high];    // khai báo phần tử đánh dâu pivot
    int left = low;   //khai báo biến bên trái
    int right = high - 1; //khai báo biến bên phải
    while(true){
        while(left <= right && arr[left] < pivot) left++; // tìm phần tử >= phần tử pivot trong mảng
        while(right >= left && arr[right] > pivot) right--; // tìm phần tử <= phần tử pivot trong mảng
        if (left >= right) break; // sau khi duyệt xong thì thoát khỏi vòng lặp
        swap(arr[left], arr[right]); // nếu chưa xong thì sử dụng hàm swap() để tráo đổi.
        left++; // Vì left hiện tại đã xét, nên cần tăng
        right--; // Vì right hiện tại đã xét, nên cần giảm
    }
    swap(arr[left], arr[high]);
    return left; // Trả về chỉ số sẽ dùng để chia đôi mảng
}

Hàm quickSort():

void quickSort(int arr[], int low, int high)
{
    if (low < high)
    {
        /* index là chỉ số nơi phần tử này đã đứng đúng vị trí
         và đây là phần tử chia mảng làm 2 mảng con trái & phải */
        int index = partition(arr, low, high);
  
        // Gọi đệ quy sắp xếp 2 mảng con trái và phải
        quickSort(arr, low, index - 1);
        quickSort(arr, index + 1, high);
    }
}

Hàm Swap():

void swap(int &a, int &b)
{
    int t = a;
    a = b;
    b = t;
}

Giải thích thuật toán:

  1. Chọn phần tử đánh dấu pivot cho mảng, ở đây mình đã chọn phần tử cuối cùng của mảng.
  2. Tạo hai biến left và right để trỏ tới hai phần tử bên trái và bên phải mảng.
  3. So sánh với phần tử pivot, nếu nhỏ hơn thì dịch chuyển qua bên trái ngược lại lớn hơn thì dịch chuyển qua bên phải.
  4. Sắp xếp các phần tử trong mảng con mới, rồi tiếp tục vòng lặp tiếp theo.

Dưới đây là ví dụ mình họa mình sử dụng thuật toán sắp xếp Quick Sort trong C / C++. Chương trình được viết bằng hai ngôn ngữ khác nhau là C và C++, các bạn có thể tham khảo nhé.

Chương trình C:

#include <stdio.h>
#include <stdbool.h>

void swap(int* a, int* b)
{
   int temp;
   temp = *a;
   *a = *b;
   *b = temp;
}
  
//  phân đoạn trong mảng
int partition (int arr[], int low, int high)
{
    int pivot = arr[high];    // khai báo phần tử đánh dâu pivot
    int left = low;   //khai báo biến bên trái
    int right = high - 1; //khai báo biến bên phải
    while(true){
        while(left <= right && arr[left] < pivot) left++; // tìm phần tử >= phần tử pivot trong mảng
        while(right >= left && arr[right] > pivot) right--; // tìm phần tử <= phần tử pivot trong mảng
        if (left >= right) break; // sau khi duyệt xong thì thoát khỏi vòng lặp
        swap(&arr[left], &arr[right]); // nếu chưa xong thì sử dụng hàm swap() để tráo đổi.
        left++; // Vì left hiện tại đã xét, nên cần tăng
        right--; // Vì right hiện tại đã xét, nên cần giảm
    }
    swap(&arr[left], &arr[high]);
    return left; // Trả về chỉ số sẽ dùng để chia đôi mảng
}
  
/* Hàm thực hiện giải thuật quick sort */
void quickSort(int arr[], int low, int high)
{
    if (low < high)
    {
        // index là chỉ số nơi phần tử này đã đứng đúng vị trí và đây là phần tử chia mảng làm 2 mảng con trái & phải 
        int index = partition(arr, low, high);
  
        // Gọi đệ quy sắp xếp 2 mảng con trái và phải
        quickSort(arr, low, index - 1);
        quickSort(arr, index + 1, high);
    }
}

void printArr(int arr[], int N)
{
   int i;
   for (i = 0; i < N; i++)
   {
       printf("%d\t", arr[i]);
   }
}

int main(void) {
  int n;
    do{
        printf("\nNhập vào số lượng phần tử có trong mảng: ");
        scanf("%d", &n);
    }while(n <= 0);
     
    int a[n];
     
    for(int i = 0;i < n;i++){
        printf("a[%d] = ",i);
       scanf("%d",&a[i]);
    };
 
    quickSort(a, 0, n - 1);
 
    printf("Mảng sau khi được sắp xếp: \n");
    printArr(a, n);
 
    printf("\n---------------------------------------\n");
    printf("Chương trình này được đăng tại codehow.net");
}

Kết quả:

bai15 03 png

Chương trình C++:

#include <iostream>
using namespace std;

//tạo hàm swap để tráo đổi các vị trí
void swap(int &a, int &b)
{
    int t = a;
    a = b;
    b = t;
}
  
//  phân đoạn trong mảng
int partition (int arr[], int low, int high)
{
    int pivot = arr[high];    // khai báo phần tử đánh dâu pivot
    int left = low;   //khai báo biến bên trái
    int right = high - 1; //khai báo biến bên phải
    while(true){
        while(left <= right && arr[left] < pivot) left++; // tìm phần tử >= phần tử pivot trong mảng
        while(right >= left && arr[right] > pivot) right--; // tìm phần tử <= phần tử pivot trong mảng
        if (left >= right) break; // sau khi duyệt xong thì thoát khỏi vòng lặp
        swap(arr[left], arr[right]); // nếu chưa xong thì sử dụng hàm swap() để tráo đổi.
        left++; // Vì left hiện tại đã xét, nên cần tăng
        right--; // Vì right hiện tại đã xét, nên cần giảm
    }
    swap(arr[left], arr[high]);
    return left; // Trả về chỉ số sẽ dùng để chia đôi mảng
}
  
/* Hàm thực hiện giải thuật quick sort */
void quickSort(int arr[], int low, int high)
{
    if (low < high)
    {
        // index là chỉ số nơi phần tử này đã đứng đúng vị trí và đây là phần tử chia mảng làm 2 mảng con trái & phải 
        int index = partition(arr, low, high);
  
        // Gọi đệ quy sắp xếp 2 mảng con trái và phải
        quickSort(arr, low, index - 1);
        quickSort(arr, index + 1, high);
    }
}

void printArr(int arr[], int N)
{
   int i;
   for (i = 0; i < N; i++)
   {
       cout<<arr[i]<<"\t";
   }
}

int main(void) {
  int n;
    do{
        cout<<"\nNhập vào số lượng phần tử có trong mảng: ";
        cin>>n;
    }while(n <= 0);
     
    int a[n];
     
    for(int i = 0;i < n;i++){
        cout<<"a["<<i<<"] = ";
       cin>>a[i];
    };
 
    quickSort(a,0, n-1);
 
    cout<<"Mảng sau khi được sắp xếp: \n";
    printArr(a, n);
 
    cout<<"\n---------------------------------------\n";
    cout<<"Chương trình này được đăng tại codehow.net";
}

Kết quả:

bai15 02 png

Như vậy là chúng ta đã cùng nhau tìm hiểu về thuật toán sắp xếp Quick Sort trong C / C++. Trong các thuật toán sắp xếp thì đây được xem là thuật toán sắp xếp nhanh nhất, tuy nhiên độ phức tạp nó khá cao so với các thuật toán khác. Các bạn nên tìm hiểu các thuật toán ở các bài viết trước của mình đã nhé. Cảm ơn các bạn rất nhiều !!!

Cùng chuyên mục:

Danh sách liên kết (Linked List) là gì? Các loại danh sách liên kết

Danh sách liên kết (Linked List) là gì? Các loại danh sách liên kết

Sử dụng đệ quy để giải bài toán tháp Hà Nội

Sử dụng đệ quy để giải bài toán tháp Hà Nội

Đệ quy tương hỗ (Mutual Recursion) trong C / C++

Đệ quy tương hỗ (Mutual Recursion) trong C / C++

Đệ quy lồng (Nested Recursion) trong C / C++

Đệ quy lồng (Nested Recursion) trong C / C++

Đệ quy đa tuyến (Exponential Recursion) trong C / C++

Đệ quy đa tuyến (Exponential Recursion) trong C / C++

Đệ quy nhị phân (Binary Recursion) trong C / C++

Đệ quy nhị phân (Binary Recursion) trong C / C++

Đệ quy đuôi (Tail Recursion) trong C / C++

Đệ quy đuôi (Tail Recursion) trong C / C++

Đệ quy tuyến tính (Linear Recursion) trong C / C++

Đệ quy tuyến tính (Linear Recursion) trong C / C++

Hàm đệ quy là gì? Các loại hàm đệ quy trong C / C++

Hàm đệ quy là gì? Các loại hàm đệ quy trong C / C++

Thuật toán sắp xếp trộn (Merge Sort) trong C / C++

Thuật toán sắp xếp trộn (Merge Sort) trong C / C++

Thuật toán sắp xếp chọn (Selection Sort) trong C / C++

Thuật toán sắp xếp chọn (Selection Sort) trong C / C++

Thuật toán sắp xếp chèn (Insertion Sort) trong C / C++

Thuật toán sắp xếp chèn (Insertion Sort) trong C / C++

Thuật toán sắp xếp nổi bọt (Bubble Sort) trong C / C++

Thuật toán sắp xếp nổi bọt (Bubble Sort) trong C / C++

Thuật toán tìm kiếm nội suy (Interpolation Search) trong C / C++

Thuật toán tìm kiếm nội suy (Interpolation Search) trong C / C++

Thuật toán tìm kiếm nhị phần (Binary Search) trong C / C++

Thuật toán tìm kiếm nhị phần (Binary Search) trong C / C++

Thuật toán tìm kiếm tuyến tính (Linear Search) trong C / C++

Thuật toán tìm kiếm tuyến tính (Linear Search) trong C / C++

Thuật toán kiểm tra năm nhuận trong C / C++

Thuật toán kiểm tra năm nhuận trong C / C++

Thuật toán kiểm tra số chẵn lẻ trong C / C++

Thuật toán kiểm tra số chẵn lẻ trong C / C++

Thuật toán tính lũy thừa trong C / C++

Thuật toán tính lũy thừa trong C / C++

Thuật toán tìm ước chung lớn nhất trong C / C++

Thuật toán tìm ước chung lớn nhất trong C / C++

Top