您的位置:首页 > 其它

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

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



①自顶向下(递归)
方法如下:
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[
4000
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),而且归并排序是稳定的

与前面所有的排序算法不一样,归并排序属于外部排序,而对于外部排序而言,与内部排序最大的区别在于外部排序在进行排序时,并不需要得到所有数据,可以将大量的数据分成若干组,分别对其进行排序,最后再综合起来排序,适合与大量数据的排序
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: