排序算法(六)---- 归并排序

本文详细介绍了归并排序的两种实现方式:自顶向下的递归实现和自底向上的非递归实现。两种方法都利用了分治策略,需要辅助空间,时间复杂度为O(NlogN),空间复杂度为O(N)。归并排序适用于大量数据的稳定排序。

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

对于归并排序,与快速排序一样,巧妙的应用了分治算法的核心思想,它将整个序列分成若干组子序列,对这些子序列进行排序后,在一步一步进行合并有序子序列,从而使得整个序列达到有序。
但针对于归并排序,有着两种不同的排序方式,一是通过整个序列进行着手,将这个序列进行一步一步的划分,自顶向下进行处理,主要步骤包括序列划分,子序列排序,以及合并,而这一方法可以通过递归来实现;与之相对的就是另外一种方式,自底向上,从最小子序列着手,将其进行两两合并,一步一步得到整个有序序列,而这也是我们归并排序的非递归实现方式

①自顶向下(递归)
方法如下:
void Merge(int arr[],int left,int right,int mid,int* tmp)
{
       int i=left;
       int j=mid+1;
       int idx=0;
       while(i<=mid&&j<=right)
       {
              if(arr[i]<arr[j])
                     tmp[idx++]=arr[i++];
              else
                     tmp[idx++]=arr[j++];
       }

       while(i<=mid)
       {
              tmp[idx++]=arr[i++];
       }
       while(j<=right)
       {
              tmp[idx++]=arr[j++];
       }

}

void MergeSort_Nor(int arr[],int left,int right,int* tmp)
{
       if(left<right)
       {
              int mid=(left&right)+((left^right)>>1);
              MergeSort_Nor(arr,left,mid,tmp);
              MergeSort_Nor(arr,mid+1,right,tmp);
              Merge(arr,left,right,mid,tmp);
              memcpy(arr+left,tmp,(right-left+1)*sizeof(arr[0]));
       }
}

void MergeSort(int arr[],int size)
{
       int* tmp=new int[size];
       int left=0;
       int right=size-1;
       MergeSort_Nor(arr,left,right,tmp);
       delete[] tmp;
}

②自底向上(非递归)
方法如下:
void Merge(int arr[],int left,int right,int mid,int* tmp)
{
       int i=left;
       int j=mid+1;
       int idx=0;
       while(i<=mid&&j<=right)
       {
              if(arr[i]<arr[j])
                     tmp[idx++]=arr[i++];
              else
                     tmp[idx++]=arr[j++];
       }

       while(i<=mid)
       {
              tmp[idx++]=arr[i++];
       }
       while(j<=right)
       {
              tmp[idx++]=arr[j++];
       }

}

void MergeSort(int arr[],int size)
{
       int* tmp=new int[size];
       int gap=1;
       while(gap<size)
       {
              for(int i=0;i<size;i+=2*gap)
              {
                     int left=i;
                     int right=i+2*gap-1;
                     int mid=i+gap-1;
                     if(right>=size)//注意越界
                           right=size-1;
                     if(mid>=size)//注意越界
                           mid=size-1;
                     Merge(arr,left,right,mid,tmp);
                     memcpy(arr+left,tmp,(right-left+1)*sizeof(arr[0]));
              }
              gap*=2;
       }

       delete[] tmp;
}

值得注意的是,归并排序不管是非递归方法,还是递归方法,都需要辅助空间的参与,但是对于递归而言,一次递归就申请一次空间会降低效率,而且需要注意释放空间,所以这里在外部直接申请出一块足够的空间,然后将其指针作为参数进行传递,而在外部进行释放,也是相当方便。

对于归并排序的时间复杂度为O(NlogN),空间复杂度为O(N),而且归并排序是稳定的

与前面所有的排序算法不一样,归并排序属于外部排序,而对于外部排序而言,与内部排序最大的区别在于外部排序在进行排序时,并不需要得到所有数据,可以将大量的数据分成若干组,分别对其进行排序,最后再综合起来排序,适合与大量数据的排序


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值