歸併排序:二路歸併

來源:互聯網
上載者:User

標籤:歸併排序   遞迴   合并   merge   二路歸併   

歸併排序(Merge Sort)是將兩個(或兩個以上)有序表合并成一個新的有序表,即把待排序序列分為若干個有序的子序列,再把有序的子序列合并為整體有序序列。

歸併排序的具體做法:

  1. 把原序列不斷地遞迴等分,直至每等份只有一個元素,此時每等份都是有序的。
  2. 相鄰等份合并,不斷合并,直至合并完全。

二路歸併

歸併排序是建立在歸併操作上的一種有效排序演算法。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。歸併排序最常用的是二路歸併,即把兩個小的有序的序列和並成一個大的有序序列:合二為一。

一個二路歸併的流程圖是這樣的:

多路歸併無非是多個有序的小序列合并成一個大的有序序列,道理和二路歸併一樣。

先來看下如何把兩個有序的序列合并成一個大的有序序列,代碼如下:

/* *把有序序列a和b,合并成c  *該演算法成立前提: a和b已經有序   */ void merge(int a[], int na, int b[], int nb, int c[]){if(a && b && c && na >0 && nb >0){int i,j,k;i = j = k = 0;//不斷地比較a和b的頭部元素,較小的存入c while(i < na && j < nb){if(a[i] <= b[j]) // <= 保持演算法的穩定性c[k++] = a[i++];elsec[k++] = b[j++];/*另一種更有效做法是這樣的 while(i < na && a[i] <= b[j])c[k++] = a[i++];while(j < nb && b[j] < a[i])c[k++] = b[j++];*/}//把a或b中剩餘的元素直接存入c /*  也可以這樣:     *  memcpy(c+k, a+i, (na-i)sizeof(int));     * 下同     */while(i < na)c[k++] = a[i++];while(j < nb)c[k++] = b[j++];}}

可以看出,二路歸併的時間複雜度是O(n),n是原序列的資料規模。以上代碼是歸併排序的基礎,弄懂了它,就很好寫歸併排序了,看下歸併排序的流程圖:


可以看出,上半部分不斷地遞迴深入:不斷地均分原序列,直到每一部分只含有一個元素。下半部分,開始遞迴返回,通過反覆調用二路歸併演算法,把相鄰的有序子序列合并成一個規模更大的序列。

理解了這些,相信就很容易寫出歸併排序的代碼了:

//把[first, mid]和[mid+1, last]範圍內的資料合併  void mergeArray(int a[], int b[], int first, int mid, int last){int i, j, k;i = first, j = mid + 1, k = 0;while (i <= mid && j <= last){while(i <= mid && a[i] <= a[j])b[k++] = a[i++];while(j <= last && a[j] < a[i])b[k++] = a[j++];}/*  也可以這樣: *  memcpy(b+k, a+i, (mid-i+1)sizeof(int)); * 下同 */while (i <= mid)b[k++] = a[i++];while (j <= last)b[k++] = a[j++];//[first,last]範圍內的資料已有序,則寫回原數組for (i = 0; i < k; i++)a[first + i] = b[i];}void mergesort(int a[], int b[], int first, int last){if (first < last){int mid = first + ((last - first) >> 1);mergesort(a, b, first, mid);mergesort(a, b, mid + 1, last);mergeArray(a, b, first, mid, last);}}void MergeSort(int a[], int n){if (a && n > 1){int *b = new int[n];  //構建輔助數組mergesort(a, b, 0, n - 1);delete[]b;}}


在排序過程中,我們使用了一個相同大小的臨時輔助數組。

演算法分析:

1.演算法的複雜度

對數組長度為n的序列進行歸併排序,則大約要進行logn次歸併,每一次合并都是線性時間O(n)。故粗略的計算出歸併排序的時間複雜度是O(nlogn)(最好、最差都是這樣)。空間複雜度是O(n)。詳細的時間複雜度分析是這樣的:

對長度為n的序列歸併排序,需要遞迴的對長度為n/2的子序列進行歸併排序,最後把兩段子序列二路歸併。遞推關係是這樣的:T(n)=2T(n/2)+O(n),顯然T(1)=O(1),解得T(n)=o(nlogn)。

2.穩定性

歸併排序是穩定的,並且是時間複雜度為o(nlogn)的幾種排序(快速排序、堆排序)中唯一穩定的排序演算法。

3.儲存結構

順序儲存和鏈式儲存都行。

另外,歸併排序多用於外排序中。


轉載請註明出處,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/34463409

若是有所協助,頂一個哦!

專欄目錄:資料結構與演算法目錄




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.