归并排序
Posted 遥远的歌s
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了归并排序相关的知识,希望对你有一定的参考价值。
归并排序算法
归并排序是将两个或两个以上的有序表组合成一个新的有序表。其基本思想是:先将N个数据看成N个长度为1的表,将相邻两个表合并,得到长度为2的N/2个有序表,进一步将相邻的表合并,得到长度为4的N/4个有序表,以此类推,直到所有数据合并成一个长度为N的有序表位置。每一次归并称为一趟。
如下图
归并排序特点:
- 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题
- 时间复杂度:O(N*logN)
- 空间复杂度:O(N)
- 稳定性:稳定
算法实现
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);
以上是关于归并排序的主要内容,如果未能解决你的问题,请参考以下文章