QuickSort là gì? Triển khai thuật toán sắp xếp nhanh

Nội Dung ChínhThuật toán QuickSort là gì?Minh họa cách triển khai thuật toán QuickSortThuật toán phân vùngPseudo code cho hàm QuickSort function:Pseudo code cho phân vùng ()Minh họa phân vùng – partition()Cách triển khai QuickSort cho 5 ngôn ngữ lập trình phổ biến nhất hiện nayTriển khai QuickSort trong C++14QuickSort trong JavaTriển khai QuickSort trong … Tiếp tục đọc QuickSort là gì? Triển khai thuật toán sắp xếp nhanh


Thuật toán Quick Sort là một trong các thuật toán sắp xếp cực hiệu quả, có khả năng ứng dụng cao nhất hiện nay. Hãy cùng Vietnix tìm hiểu chi tiết về Quick Sort là gì và cách triển khai Quick Sort trong các môi trường ngôn ngữ lập trình khác nhau từ C++14, Java, Python cho đến C#, Javascript.

Thuật toán QuickSort là gì?

Thuật toán QuickSort là một dạng thuật toán sắp xếp, được xây dựng dựa trên nguyên tắc thuật toán chia để trị. QuickSort hoạt động dựa trên việc phân chia các mảng dữ liệu thành các nhóm phần tử nhỏ hơn. Tuy nhiên, các lập trình viên sẽ cần một thời gian đáng kể để làm quen, nghiên cứu và học cách “làm chủ” Thuật toán QuickSort. Các phiên bản QuickSort khác nhau sẽ chọn pivot theo những cách khác nhau.

  • Luôn chọn phần tử đầu tiên làm trục.
  • Luôn chọn phần tử cuối cùng làm trục.
  • Chọn một phần tử ngẫu nhiên làm trục quay.
  • Chọn trung vị làm trục.
Thuật toán sắp xếp nhanh QuickSort 
Thuật toán sắp xếp nhanh Quick Sort 

Quá trình đóng vai trò quan trọng trong QuickSort là phân vùng (). Phân vùng là việc đặt một mảng và một phần tử x của mảng làm trụ, đặt x vào đúng vị trí của nó trong mảng đã sắp xếp và đặt tất cả các phần tử nhỏ hơn x và trước x, đặt tất cả các phần tử lớn hơn x và sau x. 

Banner Hosting Cao Cấp dành cho SEOer

Minh họa cách triển khai thuật toán QuickSort

Dưới đây sẽ là minh họa chung cho khả năng sắp sếp của thuật toán QuickSort.

Thuật toán phân vùng

Có nhiều cách để thực hiện thuật toán phân vùng. Chúng ta bắt đầu từ phần tử ngoài cùng bên trái và theo dõi chỉ số của các phần tử nhỏ hơn (hoặc bằng) là i. Trong quá trình duyệt, nếu tìm thấy một phần tử nhỏ hơn, bạn cần hoán đổi phần tử hiện tại với arr [i]. Nếu không, bạn nên bỏ qua phần tử hiện tại.

Pseudo code cho hàm QuickSort function:

/* low  –> Starting index,  high  –> Ending index */
quickSort(arr[], low, high) 
    if (low < high) 
        /*  pi là partitioning index, arr [pi] hiện ở đúng vị trí  */
        pi = partition(arr, low, high);
        quickSort(arr, low, pi – 1);  // Trước pi
        quickSort(arr, pi + 1, high); // Sau pi
    

Pseudo code cho phân vùng ()

/* Hàm này nhận phần tử cuối cùng làm pivot, đặt phần tử pivot vào đúng vị trí và đặt tất cả các phần tử nhỏ hơn (nhỏ hơn pivot) ở bên trái của pivot, còn các phần tử lớn hơn ở bên phải của pivot*/.

partition (arr[], low, high)

    // pivot (Phần tử được đặt đúng vị trí)
pivot = arr[high];  
 i = (low – 1)  // Index của smaller element và indicates the 
// vị trí bên phải của pivot được tìm thấy cho đến nay
for (j = low; j <= high- 1; j++)
 // Nếu element hiện tại nhỏ hơn pivot
if (arr[j] < pivot)
i++;    // chỉ số increment index của smaller element
 hoán đổi arr[i] và arr[j]
     
 
    swap arr[i + 1] and arr[high])
return (i + 1)

Minh họa phân vùng – partition()

Consider: arr[] = 10, 80, 30, 90, 40, 50, 70
 Indexes:  0   1   2   3   4   5   6 
 low = 0, high =  6, pivot = arr[h] = 70
 Khởi tạo index của smaller element, i = -1
Minh họa phân vùng quick sort
Traverse elements from j = low to high-1
 j = 0: Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j])
 i = 0 
arr[] = 10, 80, 30, 90, 40, 50, 70 // Không hay đổi gì vì i và j giống nhau
 j = 1: Since arr[j] > pivot, do nothing
j = 2 : Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j])
i = 1
arr[] = 10, 30, 80, 90, 40, 50, 70 // Hoán đổi 80 và 30 
  • j = 3 : Since arr[j] > pivot, do nothing // Không thay đổi i và arr[]
  • j = 4 : Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j])
  • i = 2
  • arr[] = 10, 30, 40, 90, 80, 50, 70 // Hoán đổi 80 và 40
  • j = 5 : Since arr[j] <= pivot, do i++ and swap arr[i] with arr[j] 
  • i = 3 
  • arr[] = 10, 30, 40, 50, 80, 90, 70 // Hoán đổi 90 và 50
  • Thoát khỏi vòng lặp vì j cao hơn -1.
  • Cuối cùng, bạn đặt trục ở vị trí chính xác bằng cách hoán đổi arr[i+1] and arr[high] (or pivot) arr[] = 10, 30, 40, 50, 70, 90, 80 // Hoán đổi 80 và 70
  • Giờ phần tử 70 đã ở đúng vị trí, tất cả các phần tử < 70 nằm trước nó còn các phần tử > 70 nằm đằng sau.
  • Vì QuickSort là một hàm đệ quy, ta gọi lại hàm phân vùng ở các phân vùng bên trái và bên phải.
  • Gọi chức năng ở phần bên phải và hoán đổi 80, 90.

Cách triển khai QuickSort cho 5 ngôn ngữ lập trình phổ biến nhất hiện nay

Dưới đây là cách triển khai QuickSort cho một số ngôn ngữ lập trình phổ biến.

Triển khai QuickSort trong C++14

/* C++ implementation of QuickSort */
#include 
using namespace std;
//Một utility function để hoán đổi 2 elements
void swap(int* a, int* b)

    int t = *a;
    *a = *b;
    *b = t;

/* Hàm này nhận element cuối cùng làm pivot, địa điểm pivot element xoay 
ở vị trí chính xác của nó trong được sắp xếp mảng và đặt tất cả nhỏ hơn (nhỏ hơn pivot) 
ở bên trái của pivot và tất cả các phần tử lớn hơn ở bên phải pivot*/
int partition (int arr[], int low, int high)

    int pivot = arr[high]; // pivot
    int i = (low - 1); // Index của smaller element và indicates 
                       //vị trí bên phải pivot được tìm thấy
    for (int j = low; j <= high - 1; j++)
    
        // Nếu current element là nhỏ hơn pivot
        if (arr[j] < pivot)
        
            i++; // increment index của element nhỏ hơn
            swap(&arr[i], &arr[j]);
        
    
    swap(&arr[i + 1], &arr[high]);
    return (i + 1);

/* Main function của implements QuickSort
arr[] --> Array to be sorted,
low --> Starting index,
high --> Ending index */
void quickSort(int arr[], int low, int high)

    if (low < high)
    
        /* pi is partitioning index, arr[p] is now
        at right place */
        int pi = partition(arr, low, high);
        // Separately sort elements before
        // partition and after partition
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    

/* Function to print an array */
void printArray(int arr[], int size)

    int i;
    for (i = 0; i < size; i++)
        cout << arr[i] << " ";
    cout << endl;

// Driver Code
int main()

    int arr[] = 10, 7, 8, 9, 1, 5;
    int n = sizeof(arr) / sizeof(arr[0]);
    quickSort(arr, 0, n - 1);
    cout << "Sorted array: n";
    printArray(arr, n);
    return 0;

QuickSort trong Java

// Java implementation of QuickSort
import java.io.*;
class GFG
// A utility function to swap two elements
static void swap(int[] arr, int i, int j)

    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;

/* Hàm này nhận phần tử cuối cùng làm pivot, địa điểm phần tử xoay ở vị trí chính xác của nó trong được sắp xếp mảng và đặt tất cả nhỏ hơn (nhỏ hơn pivot) ở bên trái của pivot và tất cả các phần tử lớn hơn ở bên phải pivot */
static int partition(int[] arr, int low, int high)

    // pivot
    int pivot = arr[high];
    // Index of smaller element and
    // indicates the right position
    // of pivot found so far
    int i = (low - 1);
    for(int j = low; j <= high - 1; j++)
    
        // If current element is smaller
        // than the pivot
        if (arr[j] < pivot)
        
            // Increment index of
            // smaller element
            i++;
            swap(arr, i, j);
        
    
    swap(arr, i + 1, high);
    return (i + 1);

/* Chức năng chính thực hiện QuickSort
          arr[] --> Array to be sorted,
          low --> Starting index,
          high --> Ending index
 */
static void quickSort(int[] arr, int low, int high)

    if (low < high)
    
        // pi is partitioning index, arr[p]
        // is now at right place
        int pi = partition(arr, low, high);
        // Separately sort elements before
        // partition and after partition
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    

// Function to print an array
static void printArray(int[] arr, int size)

    for(int i = 0; i < size; i++)
        System.out.print(arr[i] + " ");
    System.out.println();

// Driver Code
public static void main(String[] args)

    int[] arr =  10, 7, 8, 9, 1, 5 ;
    int n = arr.length;
    quickSort(arr, 0, n - 1);
    System.out.println("Sorted array: ");
    printArray(arr, n);

Bạn có thể tìm hiểu thêm về ngôn ngữ này trong bài tìm hiểu ngôn ngữ lập trình Java cho người mới của Vietnix.

Triển khai QuickSort trong Python 3

# Python3 implementation of QuickSort 
# Chức năng tìm vị trí phân vùng phân vùng def (mảng, thấp, cao):
  # Chọn phần tử ngoài cùng bên phải làm pivot
  pivot = array[high]
  # Con trỏ cho phần tử lớn hơn
  i = low - 1
  # Đi qua tất cả các yếu tố
  # So sánh từng phần tử với pivot
  for j in range(low, high):
    if array[j] <= pivot:
      # If element smaller than pivot is found
      # swap it with the greater element pointed by i
      i = i + 1
      # Swapping element at i with element at j
      (array[i], array[j]) = (array[j], array[i])
  # Hoán đổi phần tử pivot với phần tử lớn hơn chỉ định
  (array[i + 1], array[high]) = (array[high], array[i + 1])
  # Trả lại vị trí từ nơi phân vùng được thực hiện
  return i + 1
# Chức năng thực hiện QuickSort
def quick_sort(array, low, high):
  if low < high:
    #Tìm phần tử trục sao cho
    # element smaller than pivot are on the left
    # element greater than pivot are on the right
    pi = partition(array, low, high)
    # Recursive call on the left of pivot
    quick_sort(array, low, pi - 1)
    # Recursive call on the right of pivot
    quick_sort(array, pi + 1, high)
# Driver code
array = [ 10, 7, 8, 9, 1, 5]
quick_sort(array, 0, len(array) - 1)
print(f'Sorted array: array')

Nếu bạn đang tìm hiểu về Python có thể tham khảo bài viết về Python là gì và ứng dụng của ngôn ngữ lập trình Python.

Triển khai QuickSort trong C#

// C# implementation of QuickSort
using System;
class GFG

  // A utility function to swap two elements
  static void swap(int[] arr, int i, int j)
  
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
  
  /* Hàm này nhận phần tử cuối cùng làm pivot, địa điểm phần tử xoay ở vị trí chính xác của nó trong được sắp xếp mảng và đặt tất cả nhỏ hơn (nhỏ hơn pivot) ở bên trái của pivot và tất cả các phần tử lớn hơn ở bên phải pivot*/
  static int partition(int[] arr, int low, int high)
  
    // pivot
    int pivot = arr[high];
    // Index of smaller element and
    // indicates the right position
    // of pivot found so far
    int i = (low - 1);
    for (int j = low; j <= high - 1; j++)
    
      // If current element is smaller
      // than the pivot
      if (arr[j] < pivot)
      
        // Increment index of
        // smaller element
        i++;
        swap(arr, i, j);
      
    
    swap(arr, i + 1, high);
    return (i + 1);
  
  /* Chức năng chính thực hiện QuickSort
              arr[] --> Array to be sorted,
              low --> Starting index,
              high --> Ending index
     */
  static void quickSort(int[] arr, int low, int high)
  
    if (low < high)
    
      // pi is partitioning index, arr[p]
      // is now at right place
      int pi = partition(arr, low, high);
      // Separately sort elements before
      // partition and after partition
      quickSort(arr, low, pi - 1);
      quickSort(arr, pi + 1, high);
    
  
  // Function to print an array
  static void printArray(int[] arr, int size)
  
    for (int i = 0; i < size; i++)
      Console.Write(arr[i] + " ");
    Console.WriteLine();
  
  // Driver Code
  public static void Main()
  
    int[] arr =  10, 7, 8, 9, 1, 5 ;
    int n = arr.Length;
    quickSort(arr, 0, n - 1);
    Console.Write("Sorted array: ");
    printArray(arr, n);
  

Triển khai QuickSort trong Javascript