1. 程式人生 > >排序系列演算法——歸併排序

排序系列演算法——歸併排序

      歸併排序是採用分治策略進行排序的一種演算法,其基本原理是將未排序的陣列劃分為兩個子陣列,分別對兩個子陣列盡心排序,然後將有序的子數組合並。歸併排序分為兩個過程:一是陣列劃分為兩個子陣列並分別進行排序,二是將兩個已排序的子陣列進行合併。

將陣列劃分為兩個子陣列並進行排序

      將陣列一分為二很簡單,關鍵是劃分之後如何排序的問題。歸併排序的做法是對陣列不斷進行劃分,直到不能劃分為止或者說不需要劃分為止,怎樣才算不需要再劃分呢?當子陣列只剩下一個或者兩個的時候就不用繼續劃分了,一個元素本來就是有序的,兩個元素只要對比一下雙方的大小就可以輕而易舉的完成排序的工作。當兩個子陣列都是有序時,將兩個字數組合併成為一個有序的陣列,然後不斷重複字數組合並的工作就可以完成原始陣列的排序。

以一個例項說明:對陣列{13,8,15,9,5,12,11}按從小到大進行排序。

 

                                                                                    圖1 歸併排序示意圖

兩個子陣列進行合併

從上圖可以看出,歸併排序其中一個很重要的步驟是對已經排好序的子陣列進行合併。以一個例項來說明合併的步驟:

C++原始碼

先給出兩個有序子數組合並的程式碼:

 1 void Merge(int array[],int p,int q,int r){
 2
int *temp1 = new int[q-p+1]; 3 int *temp2 = new int[r-q]; 4 for(int i=p;i<=q;i++){ 5 temp1[i-p]=array[i]; 6 } 7 for(int i=q+1;i<=r;i++){ 8 temp2[i-q-1]=array[i]; 9 } 10 int k=0; 11 int z=0; 12 for(int i=p;i<=r;i++){ 13 if
((temp1[k]<temp2[z]&&k<q-p+1)||z>=r-q){ 14 array[i]=temp1[k]; 15 k++; 16 } 17 else{ 18 array[i]=temp2[z]; 19 z++; 20 } 21 } 22 }

      歸併排序劃分合併其實是一個遞迴的過程,原始陣列劃分為兩個子陣列,兩個子陣列再細分成各自的子陣列,直到子陣列只剩下一個或者兩個元素為止。最後將子陣列逐步進行合併得出最後已排序的陣列。

 1 void MergeSort(int array[],int p,int q,int r){
 2     if(r-p==1){
 3         if(array[p]>array[r]){
 4             swap(array,p,r);
 5         }
 6         return;
 7     }
 8     if(r-p==0){
 9         return;
10     }
11     int t=floor((p+q)/2);
12     int t1 =floor((q+1+r)/2);
13     MergeSort(array,p,floor((p+q)/2),q);
14     MergeSort(array,q+1,floor((q+1+r)/2),r);
15     Merge(array,p,q,r);
16 }

所有原始碼:

 1 #include "stdafx.h"
 2 #include <iostream>
 3 using namespace std;
 4 
 5 //兩個位置的資料互換
 6 void swap(int array[],int num1,int num2){
 7     int temp = array[num1];
 8     array[num1]=array[num2];
 9     array[num2]=temp;
10 }
11 
12 //合併有序的兩個序列
13 void Merge(int array[],int p,int q,int r){
14     int *temp1 = new int[q-p+1];
15     int *temp2 = new int[r-q];
16     for(int i=p;i<=q;i++){
17         temp1[i-p]=array[i];
18     }
19     for(int i=q+1;i<=r;i++){
20         temp2[i-q-1]=array[i];
21     }
22     int k=0;
23     int z=0;
24     for(int i=p;i<=r;i++){
25         if((temp1[k]<temp2[z]&&k<q-p+1)||z>=r-q){
26             array[i]=temp1[k];
27             k++;
28         }
29         else{
30             array[i]=temp2[z];
31             z++;
32         }
33     }
34 }
35 
36 //歸併排序
37 void MergeSort(int array[],int p,int q,int r){
38     if(r-p==1){
39         if(array[p]>array[r]){
40             swap(array,p,r);
41         }
42         return;
43     }
44     if(r-p==0){
45         return;
46     }
47     int t=floor((p+q)/2);
48     int t1 =floor((q+1+r)/2);
49     MergeSort(array,p,floor((p+q)/2),q);
50     MergeSort(array,q+1,floor((q+1+r)/2),r);
51     Merge(array,p,q,r);
52 }
53 
54 int main(int argc, _TCHAR* argv[])
55 {
56     int temp[]={6,10,4,7,15,12,8,11,9,5};
57     MergeSort(temp,0,4,9);
58     return 0;
59 }

相關推薦

排序系列演算法——歸併排序

      歸併排序是採用分治策略進行排序的一種演算法,其基本原理是將未排序的陣列劃分為兩個子陣列,分別對兩個子陣列盡心排序,然後將有序的子數組合並。歸併排序分為兩個過程:一是陣列劃分為兩個子陣列並分別進行排序,二是將兩個已排序的子陣列進行合併。 將陣列劃分為兩個子陣列並進行排序       將陣列一

排序系列演算法——堆排序

堆:大根堆與小根堆       堆排序是建立在堆基礎上的排序方法,首先了解一下什麼是堆。       常用的堆一般有兩種,大根堆和小根堆。堆可以看做是一棵二叉樹,其父節點的值總是大於(大根堆)或者小於(小根堆)子節點的值。舉一個例子:                            圖1 不滿足

排序算法系列歸併排序演算法

概述 上一篇我們說了一個非常簡單的排序演算法——選擇排序。其複雜程式完全是冒泡級的,甚至比冒泡還要簡單。今天要說的是一個相對比較複雜的排序演算法——歸併排序。複雜的原因不僅在於歸併排序分成了兩個部分進行解決問題,而是在於,你需要一些演算法的思想支撐。 歸併排

演算法 歸併排序小述

一、概述 本節主要簡單介紹一下歸併排序演算法,歸併排序(MERGE-SORT)是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序

知識點11:常見的排序演算法歸併排序

相信看過常見的排序演算法——快速排序的朋友們都記得,我們在介紹它的時候便闡述了使用快排的兩種策略,分別是分治和遞迴。它的原理是:通過遞迴的方式,利用某個基底,不斷將數列劃分為更小的部分。直到小陣列不能再拆分的時候,便已經完成了排序。而今天要介紹的歸併排序,與它有很多相近的地方,不過也有很

排序演算法歸併排序(關鍵詞:資料結構/演算法/排序演算法/歸併排序

假定:有 1 個亂序的數列 nums ,其中有 n 個數。 要求:排好序之後是 從小到大 的順序。 歸併排序演算法 程式碼 def merge(a, b): res = [] A = 0 B = 0 while A<len(a) and B<len(b

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

歸併排序C++ 歸併排序從小到大排序:首先讓陣列中的每一個數單獨成為長度為1的區間, 然後兩兩一組有序合併,得到長度為2的有序區間,依次進行,直到合成整個區間。 #include <iostream> using namespace std; /

高階排序演算法-歸併排序

輔助工具 歸併排序 O(nlogn)級別演算法 需要額外的輔助空間 穩定的排序演算法 對於排序演算法穩定性的定義, 這裡直接引用百度詞條: 假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,即在原序列中,r

資料結構和演算法 | 歸併排序演算法原理及實現和優化

歸併排序(MERGE-SORT)是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。 歸併排序的原理 歸

圖解算法系列歸併排序

(1)演算法描述 對於給定的線性序列,將當前序列不斷的進行分組,當每個分組的資料只有一個元素時,代表這個分組是有序的,那麼向上合併。每一層兩兩合併,合併的過程是,開闢一個新空間,使用兩個指標同時掃描兩個有序的分組,使得較小的元素或者較大的元素先進入新空間。在不斷的比較之後,如果一個分組的元素為空,直接拷貝另

[排序演算法]--歸併排序的Java實現

歸併排序(2-路歸併):歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用,歸併排序將兩個已排序的表合併成一個表。 下面先看一個歸併排序過程的示例: 待排序列(14,12

排序算法系列歸併排序(Merge sort)(C語言)

通俗理解:運用分而治之的思想,編寫遞迴函式,將大陣列排序轉化為小陣列排序,最後再將其合併。void merge_sort(int*p,int low,int high) { int mid = (low+high)/2; if (low <high) { m

我要學大資料之演算法——歸併排序

簡單粗暴的解釋:內部有序外部無序的兩個陣列的排序。 歸併排序以O(NlogN)最壞情形時間執行,而所使用的比較次數幾乎是最優的。它是遞迴演算法一個好的例項。 典型應用場景:MapReduce。  遞迴:一個方法呼叫自己本身。其關鍵點是要找到結束方法遞迴呼叫的條件出口。

PHP實現排序演算法----歸併排序(Merging Sort)

基本思想: 歸併排序:就是利用歸併(合併)的思想實現的排序方法。它的原理是假設初始序列含有 n 個元素,則可以看成是 n 個有序的子序列,每個子序列的長度為 1,然後兩兩歸併,得到 ⌈ n / 2⌉ (⌈ x ⌉ 表示不小於 x 的最小整數)個長度為 2 或

演算法排序演算法——歸併排序

前言        歸併排序是分治法在排序問題上的運用,因此為了更好地瞭解歸併排序,首先了解一下分治法。分治法的基本思想是:將原問題分解為幾個規模較小但是類似於原問題的子問題,遞迴地求解這些子問題,然後合併子問題的解來建立原問題的解。       分治模式在每層遞

演算法 歸併排序的複雜度分析(含圖解流程和Master公式)

圖解流程 整體流程如下: 細節流程: 第一步: 第二步: 第三步: 第四步: 第五步: 第六步: 第七步: 第八步:

算法系列歸併排序

hello,我的小可愛們,今天呢,向大家介紹一種排序演算法-歸併排序。歸併排序(MERGE-SORT)是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。那什麼是分治呢?分治-字面上的解釋是“分而治之”

演算法 -- 歸併排序之自然排序

定義: 歸併排序是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法的一個典型應用.應該將已經有序的子序列合併,得到完全有序的序列:即先使每個子序列有序,再使子序列段間有序.若將兩個有序表合併成一個有序表,稱為二路歸併. [摘錄於維

排序演算法---歸併排序

歸併排序的實現分為遞迴實現與非遞迴(迭代)實現。遞迴實現的歸併排序是演算法設計中分治策略的典型應用,我們將一個大問題分割成小問題分別解決,然後用所有小問題的答案來解決整個大問題。非遞迴(迭代)實現的歸併排序首先進行是兩兩歸併,然後四四歸併,然後是八八歸併,一直

Java 排序演算法-歸併排序

演算法思想 歸併排序(MergeSort)是將兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序序列分為若干個子序列,每個子序列是有序的。然後再把有序子序列合併為整體有序序列。 歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(D