归并排序算法非递归思想
归并排序的非递归实现主要在于子序列的划分;
1、首先需要一个临时数组以及左右两个子序列的区间;
2、从区间长度为1开始(递增两倍)将原数组划分成多对左右两个子序列;
3、依次将多对左右子序列进行比较,并按顺序存入临时数组中
4、再将临时数组排序好的序列再复制到原数组中
5、最后区间长度两倍增长,重复以上操作,即归并
排序过程图示
二路归并排序算法
将相邻的两个段(本身已经是有序的)的数据合并到一块,合并完成后整个段依旧有序
初始时,认为单个数据就是有序的一个段
首先书写需要用到的辅助函数
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
/*辅助函数:
1.打印数据
2.判断整个数据序列是否已经有序
3.交互两个数据swap方法
*/
void Show(int *arr,int len)//打印数据
{
for(int i=0;i<len;++i)
{
printf("%d ",arr[i]);
}
printf("\n");
}
bool IsSort(int *arr,int len)//判断整个数据序列是否已经有序
{
for(int i=0;i<len-1;++i)
{
if(arr[i]>arr[i+1])
{
return false;
}
}
return true;
}
void SwapValue(int *a,int *b)//交互两个数据swap方法
{
int tmp=*a;
*a=*b;
*b=tmp;
}
图解:
l1:第一个段的第一个元素下标
h1:第一个段的最后一个元素下标
l2:第二个段的第一个元素下标
h2:第二个段的最后一个元素下标
实现二路归并算法
void Meger(int *arr,int len,int section_size,int *brr)
{
int l1=0;
int h1=l1+section_size-1;
int l2=h1+1;
int h2=l2+section_size<len?l2+section_size-1:len-1;
int brr_index=0;
//有两个归并段
while(l2<len)
{
//两个归并段中都有数据时
while(l1<=h1&&l2<=h2)
{
if(arr[l1]<arr[l2])
{
brr[brr_index++]=arr[l1++];
}
else
{
brr[brr_index++]=arr[l2++];
}
}
//剩下一个归并段有数据
while(l1<=h1)
{
brr[brr_index++]=arr[l1++];
}
while(l2<=h2)
{
brr[brr_index++]=arr[l2++];
}
l1=h2+1;
h1=l1+section_size-1;
l2=h1+1;
h2=l2+section_size<len?l2+section_size-1:len-1;
}
//仅剩下一个归并段
while(l1<len)
{
brr[brr_index++]=arr[l1++];
}
//将brr的数据全部导入到arr中
for(int i=0;i<len;++i)
{
arr[i]=brr[i];
}
}
void MegerSort(int *arr,int len)
{
int *brr=(int *)malloc(sizeof(arr[0])*len);
assert(brr!=NULL);
for(int i=1;i<len;i*=2)
{
Meger(arr,len,i,brr);
}
free(brr);
}
最后完成主函数
int main()
{
int arr[]={7,87,29,75,41,50,62,92,69,22,76,77,35};
Show(arr,sizeof(arr)/sizeof(arr[0]));
MegerSort(arr,sizeof(arr)/sizeof(arr[0]));
Show(arr,sizeof(arr)/sizeof(arr[0]));
return 0;
}
运行结果
二路归并算法分析
时间复杂度 O(nlogn)
空间复杂度 O(n)
稳定性: 稳定