归并排序的基本思想是:将待排序文件看成n个长度为1的有序子文件,把这些子文件两两归并,得到 n/2 个长度为2的有序子文件,然后再把 n/2 个有序子文件两两归并,如此这样反复进行下去,直到最后得到一个长度为n的有序序列为止。
归并排序的核心操作是将数组中,前后相邻的两个有序序列,归并为一个有序序列。
void Merge(int a[] , int b[] , int i , int m , int n) { int j , k ; for(k = i , j = m + 1 ; k <= m && j <= n ; k++) { if(a[i] <= a[j]) b[k] = a[i++] ; else b[k] = a[j++] ; } while(i <= m) b[k++] = a[i++] ; while(j <= n) b[k++] = a[j++] ; }
每一趟归并排序的操作,就是将两个有序的子文件归并为一个有序文件。例如上面的第一个有序子文件为a[ i…… m] , 第二个有序子文件为a[m+1……n]。将这两个有序子文件合并为一个文件放在数组 b 中。
void Msort(int a[] , int b[] , int s , int t) { // 对a[s……t]进行归并排序,排序后的记录存入b[s……t] int *c = new int[t-s+2] ; //开设用于存放归并排序中间结果的辅助空间 if(s == t) b[s] = a[s] ; else { int m = (s+t)/2 ; //将a[s……t]平分为a[s……m]和a[m+1……t] ; Msort(a,c,s,m) ; //递归地将a[s……m]归并为有序的c Msort(a,c,m+1,t) ; Merge(c,b,s,m,t) ; }
归并排序的时间复杂度为O(nlogn),空间复杂度为O(n) ;
相当于二叉树的后序遍历:
#include<stdio.h> #include<stdlib.h> void Merge(int a[] , int b[] , int i , int m , int n) { int j , k ; for(k = i , j = m + 1 ; k <= m && j <= n ; k++) { if(a[i] <= a[j]) b[k] = a[i++] ; else b[k] = a[j++] ; } while(i <= m) b[k++] = a[i++] ; while(j <= n) b[k++] = a[j++] ; } void Msort(int a[] , int b[] , int s , int t) { int *c = new int[t-s+2] ; if(s == t) b[s] = a[s] ; else { int m = (s+t)/2 ; Msort(a,c,s,m) ; Msort(a,c,m+1,t) ; Merge(c,b,s,m,t) ; } } int main() { int a[] = {9,8,7,6,5,4,3,2,1} ; int b[10] ; Msort(a,b,0,8) ; int i = 0 ; for(; i < 9 ; i++) printf("%d ",b[i]) ; printf("\n") ; return 0 ; }
原文地址:http://www.cnblogs.com/scottding/p/3851926.html