排序演算法分析【五】:歸併排序(附Python&C++代碼),演算法分析python

來源:互聯網
上載者:User

排序演算法分析【五】:歸併排序(附Python&C++代碼),演算法分析python

歸併排序:將兩個已經排序的串列合并成一個串列的操作。

演算法原理

先看動態圖:


演算法描述如下:

演算法實現Python版:

#-*- encoding: utf-8 -*-        def merge_sort(list_one, list_two):    # 歸併排序    list_merge = []    i = 0; j = 0     while i < len(list_one) and j < len(list_two):        if list_one[i] <= list_two[j]:            list_merge.append(list_one[i])            i += 1         else:            list_merge.append(list_two[j])            j += 1        print 'i = {}, j = {}'.format(i, j)        print list_merge    while i < len(list_one):        list_merge.append(list_one[i])        i += 1     while j < len(list_two):        list_merge.append(list_two[j])        j += 1     return list_merge        list_one = [1, 3, 5, 6, 8, 10, 12, 13]list_two = [2, 4, 7, 9, 11, 14, 15, 16, 17, 18]print merge_sort(list_one, list_two)
結果為:

>>> ================================ RESTART ================================>>> i = 1, j = 0[1]i = 1, j = 1[1, 2]i = 2, j = 1[1, 2, 3]i = 2, j = 2[1, 2, 3, 4]i = 3, j = 2[1, 2, 3, 4, 5]i = 4, j = 2[1, 2, 3, 4, 5, 6]i = 4, j = 3[1, 2, 3, 4, 5, 6, 7]i = 5, j = 3[1, 2, 3, 4, 5, 6, 7, 8]i = 5, j = 4[1, 2, 3, 4, 5, 6, 7, 8, 9]i = 6, j = 4[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]i = 6, j = 5[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]i = 7, j = 5[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]i = 8, j = 5[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13][1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]>>> 
C++版:

#include <iostream>using namespace std;void print (int st_bf[], size_t size){    for (size_t i = 0; i < size; i++)    {        cout<< st_bf[i] << " ";    }    cout<< endl;}void merge_sort(int *list_one, size_t len_list_one,                int *list_two, size_t len_list_two){    // 歸併排序    // 申請空間    int list_merge[len_list_one+len_list_two];    size_t i = 0, j = 0, k = 0; // k儲存合并後的長度    for ( ; (i<len_list_one) and (j<len_list_two); ++k){        if (list_one[i] <= list_two[j]){            list_merge[k] = list_one[i++];        } else {            list_merge[k] = list_two[j++];        }        cout << "i = " << i << ", j = " << j << ", k = " << k << endl;        print(list_merge, k+1);    }    // 以下複製尾部大元素序列    while (i < len_list_one) list_merge[k++] = list_one[i++];    while (j < len_list_two) list_merge[k++] = list_two[j++];    cout << "i = " << i << ", j = " << j << ", k = " << k << endl;    print(list_merge, k);}int main(){    int list_one[] = {1, 3, 5, 6, 8, 10, 12, 13};    int list_two[] = {2, 4, 7, 9, 11, 14, 15, 16, 17, 18};    size_t len_list_one = sizeof(list_one)/sizeof(list_one[0]);    size_t len_list_two = sizeof(list_two)/sizeof(list_two[0]);    merge_sort(list_one, len_list_one, list_two, len_list_two);    return 0;}
結果同上,不在貼出。

本文由@The_Third_Wave(Blog地址:http://blog.csdn.net/zhanh1218)原創。還有未涉及的,會不定期更新,有錯誤請指正。

如果你看到這篇博文時發現沒有不完整,那是我為防止爬蟲先發布一半的原因,請看原作者Blog。

如果這篇博文對您有協助,為了好的網路環境,不建議轉載,建議收藏!如果您一定要轉載,請帶上尾碼和本文地址。



插入排序,選擇排序,快速排序,歸併排序的原理都是是什?哪個要記憶體量最大?

baike.baidu.com/view/58783.htm
排序是電腦內經常進行的一種操作,其目的是將一組“無序”的記錄序列調整為“有序”的記錄序列。
內部排序和外部排序:
若整個排序過程不需要訪問外存便能完成,則稱此類排序問題為內部排序;
反之,若參加排序的記錄數量很大,整個序列的排序過程不可能在記憶體中完成,則稱此類排序問題為外部排序。
內部排序的過程是一個逐步擴大記錄的有序序列長度的過程。
內排序的方法有許多種,按所用策略不同,可歸納為五類:插入排序、選擇排序、交換排序、歸併排序和分配排序。
其中,插入排序主要包括直接插入排序和希爾排序兩種;選擇排序主要包括直接選擇排序和堆排序;交換排序主要包括氣(冒)泡排序和快速排序。
一、冒泡排序
已知一組無序資料a[1]、a[2]、……a[n],需將其按升序排列。首先比較a[1]與a[2]的值,若a[1]大於a[2]則交換兩者的值,否則不變。再比較a[2]與a[3]的值,若a[2]大於a[3]則交換兩者的值,否則不變。再比較a[3]與a[4],以此類推,最後比較a[n-1]與a[n]的值。這樣處理一輪後,a[n]的值一定是這組資料中最大的。再對a[1]~a[n-1]以相同方法處理一輪,則a[n-1]的值一定是a[1]~a[n-1]中最大的。再對a[1]~a[n-2]以相同方法處理一輪,以此類推。共處理n-1輪後a[1]、a[2]、……a[n]就以升序排列了。
優點:穩定,比較次數已知;
缺點:慢,每次只能移動相鄰兩個資料,移動資料的次數多。
二、選擇排序
已知一組無序資料a[1]、a[2]、……a[n],需將其按升序排列。首先比較a[1]與a[2]的值,若a[1]大於a[2]則交換兩者的值,否則不變。再比較a[1]與a[3]的值,若a[1]大於a[3]則交換兩者的值,否則不變。再比較a[1]與a[4],以此類推,最後比較a[1]與a[n]的值。這樣處理一輪後,a[1]的值一定是這組資料中最小的。再將a[2]與a[3]~a[n]以相同方法比較一輪,則a[2]的值一定是a[2]~a[n]中最小的。再將a[3]與a[4]~a[n]以相同方法比較一輪,以此類推。共處理n-1輪後a[1]、a[2]、……a[n]就以升序排列了。
優點:穩定,比較次數與冒泡排序一樣;
缺點:相對之下還是慢。
三、插入排序
已知一組升序排列資料a[1]、a[2]、……a[n],一組無序資料b[1]、b[2]、……b[m],需將二者合并成一個升序數列。首先比較b[1]與a[1]的值,若b[1]大於a[1],則跳過,比較b[1]與a[2]的值,若b[1]仍然大於a[2],則繼續跳過,直到b[1]小於a數組中某一資料a[x],則將a[x]~a[n]分別向後移動一位,將b[1]插入到原來a[x]的位置這就完成了b[1]的插入。b[2]~b[m]用相同方法插入。(若無數組a,可將b[1]當作n=1的數組a)
優點:穩定,快;
缺點:比較次數不一定,比較次數越少,插入點後的資料移動越多,特別是當資料總量龐大的時候,但用鏈表可以解決這個問題。
四、縮小增量排序
由希爾在1959年提出,又稱希爾排序(shell排序)。
已知一組無序資料a[1]、a[2]......餘下全文>>
 
歸併排序演算法

兩種歸併排序演算法的實現:二路歸併排序和基本歸併排序(虛擬消除遞迴的二路歸併排序)
#define ARRAY_SIZE 1024

int B[1024]; //使用一個全域變數,避免歸併排序中每次都重新申請和釋放空間造成的開銷

template <typename T>
void Merge(T A[], int l, int m, int h)
{
int i = l;
int j = m+1;
int k = 0;

while(i<=m&&j<=h)
{
if(A[i]<A[j])
{
B[k++] = A[i];
i++;
}
else
{
B[k++] = A[j];
j++;
}
}

while(i<=m)
{
B[k++] = A[i++];
}

while(j<=h)
{
B[k++] = A[j++];
}

for(i=l; i<=h; i++)
{
A[i] = B[i-l];
}
}

//二路歸併排序的實現

template <typename T>
void MergeSort(T a[], int l, int h)
{
int m = (h+l)/2;
if(l>=h)
{
return;
}

if(l+1==h)
{
if(a[l]>a[h])
{
std::swap(a[l], a[h]);
}

return;
}

MergeSort(a, l, m);
MergeSort(a, m+1, h);
Merge(a, l, m, h);
}

//將a經過步長s歸併到b中,n表示數組的大小
template <typename T>
void Merge2(T a[], T b[], int s, int n)
{
int m = 0;

//從頭至尾按照步長s進行相鄰資料的合并
for(int i=0; i<n; i+=2*s)
{
int j = i; //合并的第一組數的起始位置
int k = i+s; //合并的第二組數的起始位置
int jE = i+s; //合并的第一組數的起始位置
int kE = i+2*s; //合并的第二組數的起始位置

while((j<jE)&&(k<kE)&&j<n && k<n)
{
if(a[j]<a[k])
{
b[m++] = a[j];
......餘下全文>>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.