LATEST

Thuật toán sắp xếp trộn (Merge 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 trộn (Merge Sort) trong C / C++. Đây là một thuật toán được sử dụng khá nhiều trong lập trình, bởi tốc độ và độ chính xác của nó khá cao so với các thuật toán khác.

Trước khi vào tìm hiểu về thuật toán sắp xếp trộn (Merge Sort) trong C / C++, chúng ta hãy tìm hiểu xem sắp xếp trộn là gì? Cách thức nó hoạt động đã nhé.

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

Sắp xếp trộn (Merge Sort) là một phương pháp sắp xếp dựa trên giải thuật Divede and Conquer (chia để trị).

Thuật toán sẽ thực hiện chia mảng ban đầu thành hai nửa, rồi thực hiện sắp xếp trên từng nửa. Sau đó gộp từng nửa lại với nhau thành một mảng đã sắp xếp hoàn chỉnh.

Mình có một ví dụ minh họa dưới đây, các bạn xem để hiểu rõ hơn về cách thức hoạt động của sắp xếp trộn nhé.

bai14 01 png

Giải thích:

  • Đầu tiên thuật toán sẽ chia mảng ban đầu gồm 7 phần tử thành hai nửa mảng con, một mảng 3 phần tử và một mảng 4 phần tử.
  • Tiếp tục chia nhỏ các mảng con thành hai nửa mảng con khác cho đến khi được kết quả như dòng thứ 4.
  • Sau khi chia xong, bây giờ đến lúc so sánh từng phần tử nhỏ rồi gom chúng lại thành từng mảng con như dòng 5, 6, 7.
  • Kết quả cuối cùng ta được mảng đã sắp xếp như dòng thứ 7 {3, 9, 10, 27, 38, 43, 82}.

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++ được chia làm hai giai đoạn đó là chia nhỏ các phần tử và sắp xếp, gộp các phần tử lại. Như vậy chúng ta cũng sẽ tạo hai hàm để xử lý bài toán.

Hàm mergeSort():

void mergeSort(int arr[], int l, int r)
{
    if (l < r)
    {
        int m = l+(r-l)/2;
        // Gọi hàm đệ quy tiếp tục chia đôi từng nửa mảng
        mergeSort(arr, l, m);
        mergeSort(arr, m+1, r);
  
        merge(arr, l, m, r);
    }
}

Hàm merge():

void merge(int arr[], int l, int m, int r)
{
    int i, j, k;
    int n1 = m - l + 1;
    int n2 =  r - m;
    int L[n1], R[n2];//tạo 2 mảng tạm thời để chứa các phần tử sau khi chia
    // Copy dữ liệu sang các mảng tạm 
    for (i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[m + 1+ j];
     // khởi tạo các giá trị ban đầu
    i = 0; 
    j = 0; 
    k = l; 
    //gộp hai mảng tạm thời vào mảng arr
    while (i < n1 && j < n2)
    {
        if (L[i] <= R[j])
        {
            arr[k] = L[i];
            i++;
        }
        else
        {
            arr[k] = R[j];
            j++;
        }
        k++;
    }
    // Copy các phần tử còn lại của mảng L vào arr nếu có 
    while (i < n1)
    {
        arr[k] = L[i];
        i++;
        k++;
    }
    // Copy các phần tử còn lại của mảng R vào arr nếu có 
    while (j < n2)
    {
        arr[k] = R[j];
        j++;
        k++;
    }
}

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

  • Trong hàm mergeSort() ta sử dụng đệ quy để chia mảng ban đầu thành hai nửa mảng con. Cứ tiếp tục chia cho đến khi không chia được nữa.
  • Tạo hai mảng tạm thời để lưu các phần tử sau khi chia và hai mảng con L, R.
  • Đối với trường hợp chỉ có một phần tử thì coi như đã sắp xếp.
  • Sau khi đã chia xong, ta gọi hàm merge() để gộp các phần tử ở mảng con L, R vào mảng lớn arr.
  • Bước cuối cùng là sắp xếp mảng đã gộp rồi tiếp tục vòng lặp tiếp theo.

Cứ như vậy cho đến khi kết thúc vòng lặp ta sẽ được một mảng đã được sắp xếp.

Dưới đây là ví dụ minh họa sử dụng thuật toán sắp xếp trộn (Merge 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 merge(int arr[], int l, int m, int r)
{
    int i, j, k;
    int n1 = m - l + 1;
    int n2 =  r - m;
  
    int L[n1], R[n2];//tạo 2 mảng tạm thời để chứa các phần tử sau khi chia
  
    // Copy dữ liệu sang các mảng tạm 
    for (i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[m + 1+ j];
  
    // khởi tạo các giá trị ban đầu
    i = 0; 
    j = 0; 
    k = l; 
 
    //gộp hai mảng tạm thời vào mảng arr
    while (i < n1 && j < n2)
    {
        if (L[i] <= R[j])
        {
            arr[k] = L[i];
            i++;
        }
        else
        {
            arr[k] = R[j];
            j++;
        }
        k++;
    }
  
    // Copy các phần tử còn lại của mảng L vào arr nếu có 
    while (i < n1)
    {
        arr[k] = L[i];
        i++;
        k++;
    }
  
    // Copy các phần tử còn lại của mảng R vào arr nếu có 
    while (j < n2)
    {
        arr[k] = R[j];
        j++;
        k++;
    }
}
  
// l là chỉ số trái và r là chỉ số phải của mảng cần được sắp xếp 
void mergeSort(int arr[], int l, int r)
{
    if (l < r)
    {
        int m = l+(r-l)/2;
        // Gọi hàm đệ quy tiếp tục chia đôi từng nửa mảng
        mergeSort(arr, l, m);
        mergeSort(arr, m+1, r);
  
        merge(arr, l, m, r);
    }
}

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]);
    };
 
    mergeSort(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ả:

bai14 03 png

Chương trình C++:

#include <iostream>
using namespace std;

void merge(int arr[], int l, int m, int r)
{
    int i, j, k;
    int n1 = m - l + 1;
    int n2 =  r - m;
  
    int L[n1], R[n2];//tạo 2 mảng tạm thời để chứa các phần tử sau khi chia
  
    // Copy dữ liệu sang các mảng tạm 
    for (i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[m + 1+ j];
  
    // khởi tạo các giá trị ban đầu
    i = 0; 
    j = 0; 
    k = l; 
 
    //gộp hai mảng tạm thời vào mảng arr
    while (i < n1 && j < n2)
    {
        if (L[i] <= R[j])
        {
            arr[k] = L[i];
            i++;
        }
        else
        {
            arr[k] = R[j];
            j++;
        }
        k++;
    }
  
    // Copy các phần tử còn lại của mảng L vào arr nếu có 
    while (i < n1)
    {
        arr[k] = L[i];
        i++;
        k++;
    }
  
    // Copy các phần tử còn lại của mảng R vào arr nếu có 
    while (j < n2)
    {
        arr[k] = R[j];
        j++;
        k++;
    }
}
  
// l là chỉ số trái và r là chỉ số phải của mảng cần được sắp xếp 
void mergeSort(int arr[], int l, int r)
{
    if (l < r)
    {
        int m = l+(r-l)/2;
        // Gọi hàm đệ quy tiếp tục chia đôi từng nửa mảng
        mergeSort(arr, l, m);
        mergeSort(arr, m+1, r);
  
        merge(arr, l, m, r);
    }
}

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];
    };
 
    mergeSort(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ả:

bai14 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 trộn (Merge Sort) trong C / C++. Ở bài viết tiếp theo, mình sẽ giới thiệu đến các bạn thuật toán sắp xếp nhanh, đây được coi là thuật toán sắp xếp nhanh nhất trong C / C++. Các bạn nhớ chú ý theo dõi nhé.

Cùng chuyên mục:

Xóa node khỏi cây nhị phân tìm kiếm

Xóa node khỏi cây nhị phân tìm kiếm

Tìm node Max và Min trong cây nhị phân tìm kiếm

Tìm node Max và Min trong cây nhị phân tìm kiếm

Xuất node con và node lá trong cây nhị phân tìm kiếm

Xuất node con và node lá trong cây nhị phân tìm kiếm

Tìm kiếm trên cây nhị phân tìm kiếm

Tìm kiếm trên cây nhị phân tìm kiếm

Duyệt cây nhị phân tìm kiếm

Duyệt cây nhị phân tìm kiếm

Thêm node vào cây nhị phân tìm kiếm

Thêm node vào cây nhị phân tìm kiếm

Cây nhị phân (Binary tree) là gì? Cơ chế hoạt động của nó

Cây nhị phân (Binary tree) là gì? Cơ chế hoạt động của nó

Cách gộp hai danh sách liên kết đôi

Cách gộp hai danh sách liên kết đôi

Tìm kiếm phần tử trong DSLK đôi

Tìm kiếm phần tử trong DSLK đôi

Xóa node trong DSLK đôi

Xóa node trong DSLK đôi

Chèn node (Insert node) vào DSLK đôi

Chèn node (Insert node) vào DSLK đôi

Duyệt danh sách liên kết đôi

Duyệt danh sách liên kết đôi

Tạo node mới trong DSLK đôi

Tạo node mới trong DSLK đôi

DSLK đôi là gì? Cấu trúc dữ liệu của DSLK đôi

DSLK đôi là gì? Cấu trúc dữ liệu của DSLK đôi

Quản lý sinh viên bằng DSLK đơn

Quản lý sinh viên bằng DSLK đơn

Tìm kiếm và sắp xếp trong DSLK đơn

Tìm kiếm và sắp xếp trong DSLK đơn

Xóa node (Delete node) trong DSLK đơn

Xóa node (Delete node) trong DSLK đơn

Chèn node (Insert node) vào DSLK đơn

Chèn node (Insert node) vào DSLK đơn

Tạo node mới trong DSLK đơn

Tạo node mới trong DSLK đơn

Cấu trúc dữ liệu của DSLK đơn

Cấu trúc dữ liệu của DSLK đơn