1. 程式人生 > >歸併排序(MergeSort)思想與實現

歸併排序(MergeSort)思想與實現

  歸併排序屬於高階的排序方法,在介紹歸併排序的思想之前,先講述一種採用比較方式的排序方法。假設有兩個已經排好序的陣列arr1[ ],arr2[ ],且均是升序或者降序,那麼可以進行以下操作:以升序為例,先建立一個尺寸大小為arr1[ ]與arr2[ ]尺寸之和的陣列temp[ ],然後同時從兩陣列的第0個元素開始遍歷,若arr1[i] < arr2[j],則可以把arr1[i]放入temp[k]中後,執行i++,k++,繼續往後比較;若arr1[i] > arr2[j],則可以把arr2[j]放入temp[k]中後,執行j++,k++,繼續往後比較;最終直到把兩個陣列中的所有元素放入陣列temp[ ]中。

  總結地說,這種比較方式的排序方法思想就是:因為兩個陣列都是有序的(假設為升序),故兩個陣列自身的後一個元素肯定不小於前一個元素,所以當兩個陣列分別從頭開始遍歷時,只要發現本陣列的當前元素比另一個數組的當前元素小,那麼該元素肯定為目前兩陣列中最小的元素。

  歸併排序就是用到的這種方法,接下來講述一下歸併排序的思想。

(1) 歸併排序的思想

  歸併排序的思想就是:首先將原始陣列對半切分,然後將所切成的兩個子陣列再次切分,直到所切分的子陣列只有1個元素為止;在此基礎上,先建立一個臨時陣列,再將最後只有1個元素的子陣列進行排序,排完序之後將所切成的兩個子陣列進行合併到臨時陣列中,合併的方法為本文開頭所描述的方法
,最後將臨時陣列中的值再重新賦值到原始陣列對應的位置中;之後,再返回最終切分操作之前的切分操作,並做相同的操作,對兩子陣列進行合併;以此類推,直到返回到原始陣列所切分成兩個子陣列為止,並最終合併成有序的陣列。
所以,該方法採用遞迴方法比較簡單,本文是演算法實現也採用遞迴的方法。
為了更好地理解該排序演算法,我們來看以下圖片: 從上圖可知,原始陣列為:1   8   6   4   10   5   3   2   22,以排升序為例,接下來進行分步操作。
  第一步:首先將原始陣列對半切分,切分成左右兩個子陣列,再將左右兩個子陣列對半切分;以此類推,最終切分成如下各子陣列:{1},{8},{6},{4},{10},{3},{5},{2},{22}。
  第二步:將{1},{8}合併成{1,8},再將{1,8},{6}合併成{1,6,8};將{4},{10}合併成{4,10};將{3},{5}合併成{3,5};將{2},{22}合併成{2,22}。   第三步:將{1,6,8},{4,10}合併成{1,4,6,8,10};將{3,5},{2,22}合併成{2,3,5,22}。   第四步:將{1,4,6,8,10},{2,3,5,22}合併成{1,2,3,4,5,6,8,10,22}。

(2) 歸併排序的實現

  本次排序演算法採用C++模版程式設計來實現,並採用了遞迴的方法。

#include <iostream>
#include <iterator>
#include <algorithm>


using namespace std;

template<class T,size_t N>
void PrintArr(T (&arr)[N])
{
    copy(arr,arr+N,ostream_iterator<T>(cout," "));
    cout << endl;
}


template<class T,size_t N>
void MergeSort(T (&arr)[N],size_t start = 0,ssize_t end = (N-1))
{
    size_t size = end + 1 -start;
    if(size <= 1) {
        return;
    }
    if(size == 2) {
        if(arr[start] > arr[end]) {
            swap(arr[start],arr[end]);
        }
        return;
    }
    ssize_t mid = size/2;
    MergeSort(arr,start,start+mid-1);
    MergeSort(arr,start+mid,end);
    size_t i(start),j(start+mid),k(0);
    T temp[size];
    while(i < (start+mid) or j <= end) {
        if(arr[i] <= arr[j] and i < (start+mid) or j == (end+1)) {
            temp[k] = arr[i];
            k++;
            i++;
        } else if(arr[j] <= arr[i] and j <=end or i == (start+mid)) {
            temp[k]= arr[j];
            k++;
            j++;
        }
    }
    i = start;
    k = 0;
    while(i <= end ) {
        arr[i] = temp[k];
        i++;
        k++;
    }
    PrintArr(arr);


    return;
}


int main()
{
    int arr[]= {1,8,6,4,10,5,3,2,22};
//    int arr[]= {1,4,5,2,4,8,9,10,22,4,6,1,8,9,1,21,34,54,2,4};
    cout << "The init:" << endl;
    PrintArr(arr);
    cout << "The sort:" << endl;
    MergeSort(arr);
    PrintArr(arr);
    cout << "The final:" << endl;
    PrintArr(arr);


}

原始陣列為:1   8   6   4   10   5   3   2   22

程式執行結果為:1   2   3   4   5   6   8   10   22

相關推薦

歸併排序MergeSort思想實現

  歸併排序屬於高階的排序方法,在介紹歸併排序的思想之前,先講述一種採用比較方式的排序方法。假設有兩個已經排好序的陣列arr1[ ],arr2[ ],且均是升序或者降序,那麼可以進行以下操作:以升序為

基數排序RadixSort思想實現

  基數排序屬於高階的排序方法,該排序演算法是在“桶排序”的基礎上所進行的改進,讀者若是想了解“桶排序”思想,可以點選這裡。接下來介紹一下基數排序的思想。 (1) 基數排序的思想   基數排序的思想就

插入排序InsertSort思想實現

  在介紹插入排序的思想之前,說一下插入排序的一個重要的優點:插入排序只有在需要排序時才會排序。該演算法的時間複雜度為:O(n^2),接下來我們來了解一下該排序的思想。 (1)插入排序的思想   插入

選擇排序SelectSort思想實現

  選擇排序屬於相對來說比較簡單的排序方法,時間複雜度為:O(n^2)。 (1) 選擇排序的思想   選擇排序的思想就是:選擇排序的本意在於每次選擇出最小或者最大的元素,將其放在陣列的前面,從而使得陣

排序CombSort思想實現

  梳排序也屬於簡單的排序演算法,也是一種不穩定的排序方法。在講述梳排序的思想之前,先介紹一下與該排序有關的一個關鍵常量:遞減率;該常量為固定值:1.3。該常量是由原作者Wlodzimierz Do

排序BucketSort思想實現

  桶排序屬於簡單而且易於理解的排序演算法,接下來介紹一下該演算法的思想。 (1) 桶排序的思想   桶排序的思想就是:首先遍歷一遍陣列,找出陣列中值最大的元素,假設最大的元素為Max;然後定義Max

Java排序演算法(三)--歸併排序MergeSort遞迴非遞迴的實現

歸併有遞迴和非遞迴兩種。 歸併的思想是: 1.將原陣列首先進行兩個元素為一組的排序,然後合併為四個一組,八個一組,直至合併整個陣列; 2.合併兩個子陣列的時候,需要藉助一個臨時陣列,用來存放當前的

歸併排序MergeSort詳解和動畫

歸併排序演算法思想:將陣列不斷二分得到子陣列,知道子陣列長度為1(自然是排序好的),對左子陣列和右子陣列分別排序, 子陣列長度為1,2,4...., 子陣列排序使用了一個輔助陣列 def exchange(arr,i,j): temp=arr[i] arr[i]=arr[

Java排序演算法分析實現:快排、氣泡排序、選擇排序、插入排序歸併排序

轉載  https://www.cnblogs.com/bjh1117/p/8335628.html   一、概述:   本文給出常見的幾種排序演算法的原理以及java實現,包括常見的簡單排序和高階排序演算法,以及其他常用的演算法知識。   簡單排序:氣泡排序、選擇排序、

資料結構演算法C++之歸併排序

上一篇部落格中實現的是自上以下的歸併排序,自上而下需要先不斷將陣列進行對半拆分(遞迴實現),然後再合併排序 其實也可以自下而上實現歸併排序,這樣使用for迴圈就可以實現,省掉了遞迴的操作 首先對陣列的每一個元素進行兩兩歸併(相鄰的兩個元素合併成一個有序陣列),然後將合併好的兩個元素的有序

快速排序Quicksort的Javascript實現

簡單 fun 遍歷數組 floor 演示 ont -s urn 元素 日本程序員norahiko,寫了一個排序算法的動畫演示,非常有趣。 這個周末,我就用它當做教材,好好學習了一下各種排序算法。 排序算法(Sorting algorithm)是計算機科學最古老、最基

kaggle入門項目:Titanic存亡預測驗證實現

tps 多參數 name 出了 運算 處理 defaults purpose sof 原kaggle比賽地址:https://www.kaggle.com/c/titanic 原kernel地址:A Data Science Framework: To Achieve 99

離散傅立葉變換DFT和快速傅立葉變換FFT原理實現

目錄 1、影象變換 2、離散傅立葉變換(Discrete Fourier Transform) 3、DFT性質 4、DFT與數字影象處理 5、FFT-快速傅立葉變換 6、DFT與FFT的演算法實現 1. 影象變換 — —數學領域中有很多種變換,如傅立葉變換、拉普拉斯變

排序演算法】歸併排序C++

歸併排序的遞迴實現 C++ class MergeSort { public: int* mergeSort(int* A, int n) { // write code he

C#歸併排序

class Program { static void Main(string[] args) { int[] arr = arrInsert(100000); merge_sort(arr,0,arr.Le

排序演算法:二路歸併排序java

public class MergeSort { /** * * @param array 待排序陣列 * @param temp 輔助陣列 * @param start 開始下標 * @param end 結束下標

八大排序演算法實戰:思想實現

摘要:   所謂排序,就是根據排序碼的遞增或者遞減順序把資料元素依次排列起來,使一組任意排列的元素變為一組按其排序碼線性有序的元素。本文將介紹八種最為經典常用的內部排序演算法的基本思想與實現,包括插入排序(直接插入排序,希爾排序)、選擇排序(直接選擇排序,堆排

平衡二叉樹AVL圖解實現

平衡二叉樹(Balanced BinaryTree)又被稱為AVL樹。它具有以下性質:它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。 平衡二叉樹一般是一個有序樹,它具有二叉樹的所有性質,其遍歷操作和二叉樹的遍歷操作相同。

java資料結構演算法之棧Stack設計實現

關聯文章:   本篇是java資料結構與演算法的第4篇,從本篇開始我們將來了解棧的設計與實現,以下是本篇的相關知識點: 棧的抽象資料型別   棧是一種用於儲存資料的簡單資料結構,有點類似連結串列或者順序表(統稱線性表),棧與線性表的最大區別是

直接插入排序、快排 AND歸併排序

插入排序的思想 n個待排序的元素有一個有序表和一個無序表組成,開始時,有序表中僅包含“一個元素”。排序工程中將“無序表中”取出一個元素,然後插入有序表中。 For(int i=1;i<a.length,i++)  { If(a[i]<a[i-1]) {A[