归并排序

Posted 遥远的歌s

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了归并排序相关的知识,希望对你有一定的参考价值。

归并排序算法

归并排序是将两个或两个以上的有序表组合成一个新的有序表。其基本思想是:先将N个数据看成N个长度为1的表,将相邻两个表合并,得到长度为2的N/2个有序表,进一步将相邻的表合并,得到长度为4的N/4个有序表,以此类推,直到所有数据合并成一个长度为N的有序表位置。每一次归并称为一趟。
如下图

归并排序特点:

  1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(N)
  4. 稳定性:稳定

算法实现

c++实现

void merge(vector<int> &arr,int begin,int mid,int end,vector<int> &res)

//res为中转数组,将合并的数据先放入res中后再重新赋给arr数组
  //待归并两列数据的头和尾
  int begin1 = begin,end1 = mid,begin2 = mid + 1,end2 = end;
  int idx = begin;//归并索引
  //两路归并
  while(begin1 <= end1 && begin2 <= end2)
  
    if(arr[begin1] <= arr[begin2])
      res[idx++] = arr[begin1++];
    else
      res[idx++] = arr[begin2++];
  
  //判断是否有剩余数据
  if(begin1 <= end1)
  
    while(begin1 <= end1)
      res[idx++] = arr[begin1++];
  
  if(begin2 <= end2)
  
    while(begin2 <= end2)
      res[idx++] = arr[begin2++];
  
  //重新赋值给arr数组
  for(int i = begin;i<end + 1;i++)
  
    arr[i] = res[i];
  

//非递归实现接口
void mergesortnor(vector<int> &arr,int size)

  //待合并区间元素个数,开始时个数为1
  int k = 1;
  //中转数组
  int* tmp = (int*)malloc(sizeof(int)*size);
  while(k < size)
  
    for(int i = 0;i<size;i += 2*k)
    
      int begin = i;
      int mid = i + k -1;
      //判断mid是否越界
      if(mid >= size - 1)
        continue;
      int end = i + 2*k - 1;
      //判断end是否越界
      if(end >= size)
        end = size - 1;
      merge(arr,begin,mid,end,tmp);
    
    k *= 2;//每次合并元素个数为原来的2倍
  

//归并排序非递归外部调用接口
void mergesort(vector<int> &arr,int size)

  mergesortnor(arr,size);

//归并排序递归实现
void mergesortr(vector<int> &arr,int begin,int end,vector<int> &tmp)

  if(begin>=end)
    return ;
  int mid = begin + (end - begin)/2;
  mergesortr(arr,begin,mid,tmp);
  mergesortr(arr,mid + 1,end,tmp);
  merge(arr,begin,mid,end,tmp);

//递归调用外部接口
void mergesortR(vector<int> &arr)

  vector<int> tmp;
  tmp.resize(arr.size(),0);
  mergesortr(arr,0,arr.size() - 1,tmp);


C语言实现

void merge(int* array,int begin,int mid ,int end,int* tmp)

  int begin1 = begin,end1 = mid,begin2 = mid + 1,end2 = end;
  int idx = begin;
  while(begin1<=end1&&begin2<=end2)
  
    if(array[begin1] <= array[begin2])
      tmp[idx++] = array[begin1++];
    else
      tmp[idx++] = array[begin2++];
  
  //查看是否有剩余元素
  if(begin1 <= end1)
    memcpy(tmp + idx,array + begin1,sizeof(int)*(end1 - begin1 + 1));
  if(begin2 <= end2)
    memcpy(tmp + idx,array + begin2,sizeof(int)*(end2 - begin2 + 1));
  memcpy(array + begin,tmp + begin,sizeof(int)*(end - begin +1));

//递归实现
void mergesortr(int* array,int begin,int end,int* tmp)

  if(begin>=end)
    return ;
  int mid = begin + (end - begin)/2;
  mergesortr(array,begin,mid,tmp);
  mergesortr(array,mid + 1,end,tmp);
  merge(array,begin,mid,end,tmp);

//非递归
void mergesortnor(int* array,int n)

  //待合并区间元素个数
  int k = 1;
  int* tmp = (int*)malloc(sizeof(int)*n);
  while(k < n)
  
    for(int i = 0;i<n;i += 2*k)
    
      int begin = i;
      int mid = i + k -1;
      //判断mid是否越界
      if(mid >= n - 1)
        continue;
      int end = i + 2*k - 1;
      //判断end是否越界
      if(end >= n)
        end = n - 1;
      merge(array,begin,mid,end,tmp);
    
    k *= 2;
  

//外部接口
void mergesort(int* array,int n)

  mergesortnor(array,n);

以上是关于归并排序的主要内容,如果未能解决你的问题,请参考以下文章

归并排序

算法 | 分治 | 归并排序

归并排序

6.6 归并排序

归并排序

归并排序