归并排序

来源:互联网 发布:js 获取get url参数 编辑:程序博客网 时间:2024/06/03 21:49

归并排序是一种重要的排序方法,虽然并不能算作最优的排序方法,但排序的原理在很多情况下都能引用到,比如求逆序数。

基本原理

1.可以在O(n)时间内将两个有序序列合并为一个有序序列:若给出两个同序排列的序列,若要将两段序列合并为一段新的有序序列只需要逐次将两段序列的段首元素中关键字较大的一个取出放入新的有序序列的末尾,当两段序列全部元素取出时新的序列将包含全部元素并且有序。

2.只含单个元素的序列有序:一个序列只有一个元素时序列为有序序列。

根据上面两个性质,先不断地通过二分将含N个元素的待排序序列划分为N段每段只含一个元素的子段,根据原理2,此时这N段子段全部有序,然后再将这N段序列按原理1的方法不断两两合并,不断合并为N/2段,N/4段,N/8段.......有序序列,最终合并为一段长度为N的序列,则序列已经排好序。

算法的实现

通过递归将序列不断二分,当序列长度为1时结束递归,这时再按照划分时序列间确定的关系进行归并。

归并时需要两个临时数组,可以在两个辅助数组的末尾额外添加一个哨兵,关键字设置为无限大,则将不存在比哨兵关键字更大的元素,之后在合并中就只需要比较关键字的大小而不再需要去判断是否某个序列已经到了末尾。

算法的时间复杂度为O(nlogn),空间复杂度为O(n)。

具体代码:

#include<iostream>#include<cstring>#include<ctime>using namespace std;#define INF 9999999typedef int any;void mergesort(any* ARRAY,int left,int right){  //对ARRAY实现排序   //归并排序是二分的原理 未排序数组长度大于1则二分   int middle=(left+right)/2;   if(middle>left)mergesort(ARRAY,left,middle);   if(right>middle)mergesort(ARRAY,middle+1,right);   //申请临时空间   any *L_ARRAY=new any[middle-left+2];   any *R_ARRAY=new any[right-middle+1];   //对临时空间赋值   for(int i=0;i<middle-left+1;i++)L_ARRAY[i]=ARRAY[left+i];   for(int i=0;i<right-middle;i++)R_ARRAY[i]=ARRAY[middle+1+i];   L_ARRAY[middle-left+1]=R_ARRAY[right-middle]=INF;//设置哨兵   //覆盖原数组   int a=0,b=0;   for(int i=0;i<right-left+1;i++){//取出较小元素      if(L_ARRAY[a]<R_ARRAY[b]){         ARRAY[left+i]=L_ARRAY[a];         a++;  //让段首位置相应加1代表以经取走这个元素      }      else{         ARRAY[left+i]=R_ARRAY[b];         b++;      }   }   delete []L_ARRAY;delete []R_ARRAY;//释放掉动态申请到的内存}int main(){   any p[10010]; //生成一组测试数据   srand(time(time_t()));   for(int i=0;i<10000;i++){      p[i]=rand();   }   mergesort(p,0,9999);   for(int i=0;i<10000;i++)cout<<p[i]<<endl;}



原创粉丝点击