归并排序

归并排序是一种采用分治策略的排序算法,通过不断将有序子序列合并成更长的有序序列,最终达到整个序列有序。该算法的时间复杂度为O(N*logN),空间复杂度为O(N),具有稳定性。文章介绍了归并排序的基本思想,特点,并提供了C++和C语言的实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

归并排序算法

归并排序是将两个或两个以上的有序表组合成一个新的有序表。其基本思想是:先将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);
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值