歸併排序(Merge Sort)

一、基本介紹

歸併排序是一種分治思想的經典排序演算法,它將原序列分成若干個子序列,通過遞歸再將序列合併起來。根據分治的思想,歸併排序的時間複雜度始終穩定在 O(nlogn)。

二、演算法描述

歸併排序演算法可以描述為分為兩步:分離和歸併。

1. 分離

為了使歸併排序可以遞歸地運行,需要將原序列分割成若干子序列,使得每個子序列的長度均為1,即子序列不可再分。然後將子序列兩兩合併,合併後的序列長度為2,繼續兩兩合併,以此類推,直到合併成原序列。

void merge_sort(int arr[], int left, int right)
{
    if (left >= right) return;

    int mid = left + (right - left) / 2;

    merge_sort(arr, left, mid);
    merge_sort(arr, mid + 1, right);

    merge(arr, left, mid, right);
}

2. 歸併

歸併是指將已經排好序的兩個子序列合併成一個序列的過程。在合併的過程中,需要使用一個臨時數組來保持排序的結果,最終將臨時數組內容複製回原數組。

void merge(int arr[], int left, int mid, int right) 
{
    int temp[right - left + 1];
    int i = left, j = mid + 1, k = 0;

    while (i <= mid && j <= right)
    {
        if (arr[i] <= arr[j])
            temp[k++] = arr[i++];
        else
            temp[k++] = arr[j++];
    }

    while (i <= mid)
        temp[k++] = arr[i++];

    while (j <= right)
        temp[k++] = arr[j++];

    for (i = left, k = 0; i <= right; ++i, ++k)
        arr[i] = temp[k];
}

三、優化方法

歸併排序演算法的關鍵在於歸併過程,因此如何優化歸併過程對演算法的性能影響較大。以下是幾種常見的優化方法:

1. 優化歸併過程

對於一些小規模數組,直接使用插入排序。經過實驗,如果數組長度為16以下時,插入排序的效率更高。

void merge_sort(int arr[], int left, int right)
{
    if (left + 16 >= right)
    {
        insert_sort(arr + left, right - left + 1);
        return;
    }

    int mid = left + (right - left) / 2;

    merge_sort(arr, left, mid);
    merge_sort(arr, mid + 1, right);

    merge(arr, left, mid, right);
}

2. 避免重複申請空間

歸併過程需要一個臨時數組來保存排序好的元素,但是每次遞歸都會申請一個新的數組,這樣會浪費空間。因此,在函數開始時申請一次空間即可,然後在遞歸的過程中直接使用同一個數組。

void merge_sort(int arr[], int left, int right, int temp[])
{
    if (left >= right) return;

    int mid = left + (right - left) / 2;

    merge_sort(arr, left, mid, temp);
    merge_sort(arr, mid + 1, right, temp);

    merge(arr, left, mid, right, temp);
}

void merge(int arr[], int left, int mid, int right, int temp[]) 
{
    // 省略
}

3. 使用尾遞歸優化

尾遞歸優化可以避免遞歸調用帶來的棧空間開銷。在歸併排序中,遞歸調用發生在分離兩個子序列的過程中。這裡採用尾遞歸優化方法,將遞歸過程轉換為循環過程,可以避免遞歸調用的棧空間開銷。

void merge_sort(int arr[], int left, int right, int temp[])
{
    while (left > 1);

        merge_sort(arr, left, mid, temp);
        left = mid + 1;
    }
}

void merge(int arr[], int left, int mid, int right, int temp[]) 
{
    // 省略
}

四、總結

歸併排序雖然有些優化方法,但它的時間複雜度始終穩定在 O(nlogn),並且適用於各種數據類型的排序,因此在實際應用中仍然有廣泛的應用。

原創文章,作者:CRGYF,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/332001.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
CRGYF的頭像CRGYF
上一篇 2025-01-20 14:10
下一篇 2025-01-20 14:10

相關推薦

  • sort()的應用及實現原理

    一、sort()基本介紹 sort()方法是在JavaScript中對數組進行排序的一種常用方法,它可以按照一定的規則將數組中的元素按照升序或降序排列。sort()方法有兩種應用方…

    編程 2025-04-24
  • Git merge –no-ff詳解

    Git是一款非常強大的版本管理工具,可以有效地管理項目的版本更新。Git merge –no-ff命令是其中的一種操作,可以在合併分支時保留分支信息和歷史記錄。本文將從…

    編程 2025-04-23
  • 深入理解 Linux sort 命令

    一、概述 Linux sort 命令是一個強大的排序工具,它可以將文件內容按照用戶指定的排序規則排序。 sort 命令默認按照字典序升序排序,但用戶可以通過參數實現自定義排序規則。…

    編程 2025-04-12
  • JS數組排序方法sort

    在JS中,數組作為一種常見的數據類型,提供了許多方便的操作方式。其中,排序是常見的一種操作,而sort方法也成為了JS中處理數組排序的基本方法。 一、JS數組排序方法 在JavaS…

    編程 2025-01-21
  • 深度剖析std::sort

    一、簡介 std::sort是C++ STL的一個排序演算法,它可以按照一定規則對一個給定的數組、向量或迭代器範圍內的元素進行排序。std::sort是非穩定排序演算法,平均時間複雜度…

    編程 2025-01-20
  • PHP sort()函數的用法與使用注意事項

    PHP sort()函數是一個非常重要也非常常用的函數,它可以對一個數組進行升序排列。在開發過程中,我們常常需要對數組進行排序,而sort()函數會在這個過程中起到非常重要的作用。…

    編程 2025-01-16
  • PHP sort()函數的用法與使用注意事項

    PHP sort()函數是一個非常重要也非常常用的函數,它可以對一個數組進行升序排列。在開發過程中,我們常常需要對數組進行排序,而sort()函數會在這個過程中起到非常重要的作用。…

    編程 2025-01-16
  • 使用Python中的sort函數進行列表排序

    一、sort函數介紹 sort函數是Python內置的一個函數,用於對列表進行排序,對於包含數字或字元串元素的列表,sort函數都可以進行比較和排序。sort函數的用法非常簡單,只…

    編程 2025-01-16
  • sort頭文件的詳細闡述

    一、sort頭文件的名稱 sort頭文件是C++的STL庫中的頭文件之一,其主要作用是為數組或容器提供排序的功能。sort本質上是一種排序演算法,其名稱來源於英語單詞「sort」,意…

    編程 2025-01-16
  • Java ArrayList Sort

    Java中的ArrayList類是一個可變數組的實現,它提供了數組的所有功能,同時還支持動態增加和刪除元素的能力。在實際開發中,ArrayList常常用於存儲一組元素,這些元素可能…

    編程 2025-01-16

發表回復

登錄後才能評論