归并排序算法

1、算法思想

分治发自顶而下实现归并排序:

(1)分治法的三个步骤
     设归并排序的当前区间是R[low..high],分治法的三个步骤是:
①分解:将当前区间一分为二,即求分裂点
                 
 

②求解:递归地对两个子区间R[low..mid]和R[mid+1..high]进行归并排序;
③组合:将已排序的两个子区间R[low..mid]和R[mid+1..high]归并为一个有序的区间R[low..high]。
  递归的终结条件:子区间长度为1(一个记录自然有序)。

(2)具体算法
    void MergeSortDC(SeqList R,int low,int high)
     {//用分治法对R[low..high]进行二路归并排序
       int mid;
       if(low<high){//区间长度大于1
          mid=(low+high)/2; //分解
          MergeSortDC(R,low,mid); //递归地对R[low..mid]排序
          MergeSortDC(R,mid+1,high); //递归地对R[mid+1..high]排序
          Merge(R,low,mid,high); //组合,将两个有序区归并为一个有序区
        }
     }//MergeSortDC

(3)算法MergeSortDC的执行过程 (略)

2、算法分析

(1)稳定性

 归并排序是一种稳定的排序。

(2)存储结构

可用顺序存储结构。也易于在链表上实现。

(3)时间复杂度

对长度为n的文件,需进行 趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。

(4)空间复杂度

需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。

  注意:
     若用单链表做存储结构,很容易给出就地的归并排序

View Code
1 #include <iostream>
2 #include <windows.h>
3
4  using namespace std;
5
6  void merge(int a[],int low,int mid,int high)
7 {
8 int n1,n2,k,i,j,b[100],c[100];
9 n1 = mid - low + 1;
10 n2 = high - mid;
11 //复制数组的前后部分到临时数组
12 for(i = 0;i < n1;i++)
13 b[i] = a[low+i];
14 for(i = 0;i < n2;i++)
15 c[i] = a[mid+i+1];
16 //把后面的元素设置到很大
17 b[n1] = 999999;
18 c[n2] = 999999;
19 //逐个扫描两个数组然后放到相应的位置
20 for(i = 0,j = 0,k = low;k <= high;k++)
21 {
22 if(b[i] <= c[j])
23 a[k] = b[i++];
24 else
25 a[k] = c[j++];
26 }
27 return;
28 }//end of merge
29
30 void mergeSort(int a[],int low,int high)
31 {
32 while(low < high)//区间长度大于1时才继续分解
33 {
34 int mid;
35 mid = (low+high)/2;
36 mergeSort(a,low,mid);//对前半部分进行排序
37 mergeSort(a,mid+1,high);//对后半部分进行排序
38 merge(a,low,mid,high);//合并
39 return; //开始的时候这里漏了return而错了很久
40 }
41 }
42
43 int main(int argc,char **argv)
44 {
45 int a[] = {2,1,4,5,2,6,1};
46 mergeSort(a,0,6);
47 for(int i=0;i<7;i++)
48 cout<<a[i]<<" ";
49 cout<<endl;
50 return 0;
51 }


posted @ 2011-05-19 20:36  elwin  阅读(331)  评论(0编辑  收藏  举报