归并排序详解

来源:互联网 发布:人工智能美女机器人 编辑:程序博客网 时间:2024/05/22 06:09

[算法定义]    

        将两个或两个以上有序的数列(或有序表),合并成一个仍然有序的数列(有序表),这种操作称为归并操作。若将两个有序表合并成一个有序表,称为二路归并。二路规并相对简单,所以重点讨论二路归并。

[算法分析]

     归并排序时的时间复杂度为O(nlgn) 其主要思想是分治法(divide and conquer),分就是要将n个元素的序列划分为两个序列,再将两个序列划分为4个序列,直到每个序列只有一个元素,最后,再将两个有序序列归并成一个有序的序列。

     例如两个序列:

     要归并成一个有序的序列,按照我们常规的方法,我们每次从两个列表开头元素选取较小的一个,直到某一个列表到达底部,再将另一个剩下部分顺序取出。其实如果将每个元素最后添加一个最大值,则无需判断是否达到列表尽头。

   如果初始是无序序列,首先把待排序区间(即无序表)中的每一个元素都看作为一个有序表,则n个元素构成n个有序表,接着两两归并(即第一个表同第二个表归并,第三个表和第四个表归并.......),得到[n/2]个长度为2的有序表(最后一个表的长度可能小于2,称此为一趟归并,然后再两丙有序表归并,得到[[n/2]/2])个长度为4的有序表(最后个表的长度可能小于4),如此进行下去,直到归并第[log2n]趟后第到一个长度为n的有序表为止。

   归并排序算法我们用递归实现,先把待排序区间[s,t]以中点二分,接着把左边组织区间排个序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的[s,t]。

[参考代码]

#include<iostream>

#include<cstdio>

#include<cstring>

using namespace std;

void mergesort(int,int);

int  a[101],r[101];//a是待排序数组,r是临时数组

int main()

{

int n,i;

cin>>n;

for(i=1;i<=n;i++)

    cin>>a[i];  //输入n个待排序数据

mergesort(1,n);//对[1,n]区间的无序数据进行归并排序

for(i=1;i<=n;i++)

cout<<a[i]<<"  ";//输出n个有序的数据

cout<<endl; 

}

 

void mergesort(int s,int t)

 {

  int m,i,j,k;

  if(s==t) return;//若区间只有一个数据就不用排了

 m=(s+t)/2; //取区间的中点

 mergesort(s,m);//以中点二分,对左边子区间进行排序

 mergesort(m+1,t);//以中点二分,对右边子区间进行排序

 i=s;

 j=m+1; 

 k=s;

 while(i<=m&&j<=t)//两个子序列从小到大合并,直到有一列结束

 {

  if (a[i]<=a[j])//选择较小的一个入新队列

  {r[k]=a[i];i++;k++;

  }

  else

  {r[k]=a[j];j++;k++;

  }

 }

 while(i<=m)//把左边子序列剩余的元素接入进来

 {

  r[k]=a[i];i++;k++;

 }

 while(j<=t)//把右边子序列剩余的元素接入进来

 {

  r[k]=a[j];j++;k++;

 }

 for(i=s;i<=t;i++)

 a[i]=r[i];   //把合并好的有序数据重新放入a数组

 }


0 0