归并排序主要讲二路归并排序
二路归并排序的基本思想:
设数组a中存放了n个数据元素,初始时把他们看成是n个长度为1的有序子数组,然后从第一个子数组开始,把相邻的子数组进行两两合并,的到n/2的整数上界个长度为2的新的有序子数组(当n为奇数时最后一个新的有序子数组的长度为1);对这些新的有序子数组在两两归并;如此重复,直到得到一个长度为n的有序数组为止。
归并排序的过程图:
归并排序的完整代码(非递归):
#include<iostream>
#include<malloc.h>
using namespace std;
void meger(int *arr,int len,int gap)
{
int *buff=(int*)malloc(sizeof(int)*len);//设置一个临时的buff
if(buff==NULL)
{
exit(0);
}
int i=0;
int low1=0;
int high1=low1+gap-1;
int low2=high1+1;
int high2=(low2+gap-1) < len ? (low2+gap-1) : (len-1);//当第二段的数据小于len时,就用第二段的数据
while(low2<len) //第二段有数据时候,第二段有数据才能进行归并
{
while(low1<=high1 && low2<= high2)
{
if(arr[low1]<=arr[low2])
{
buff[i++]=arr[low1++];
}
else if(arr[low1]>arr[low2])
{
buff[i++]=arr[low2++];
}
}
while(low1<=high1)//第一段中有剩余,一定不要忘记写等号
{
buff[i++]=arr[low1++];
}
while(low2<=high2)//第二段中有剩余,不要忘记写等号
{
buff[i++]=arr[low2++];
}
low1=high2+1;
high1=low1+gap-1;
low2=high1+1;
high2=(low2+gap-1) <len ? (low2+gap-1) : (len-1) ;
}
while(low1<len)//只有第一段,没有第二段
{
buff[i++]=arr[low1++];
}
for(int j=0;j<len;++j)
{
arr[j]=buff[j];//把数据拷贝过来
}
free(buff);
}
void merger_sort(int *arr,int len)
{
for(int gap=1;gap<len;gap*=2)//把带排序的数组进行排序
{
meger(arr,len,gap);
}
}
int main()
{
int arr[]={12,56,89,45,1,46};
int len=sizeof(arr)/sizeof(arr[0]);
merger_sort(arr,len);
for(int i=0;i<len;i++)
{
cout<<arr[i]<<" ";
}
cout<<endl;
}
归并排序的代码(递归):
#include<iostream>
#include<malloc.h>
using namespace std;
#define maxsize 10
void megering(int *left,int left_size,int *right,int right_size)
{
int i=0;
int j=0;
int k=0;
int temp[maxsize];//用来存储排序的数据
while(i<left_size && j<right_size)
{
if(left[i]<=right[j])//左边数据《 右边的数据
{
temp[k++]=left[i++];//就把左边的数据存储到temp数组中
}
else
{
temp[k++]=right[j++];//右边的数据小,就存储右边的数据
}
}
while(i<left_size)//左边的数据有剩余,直接把左边的数据拷贝到temp数组中
{
temp[k++]=left[i++];
}
while(j<right_size)//右边的数据有剩余,就把右边的数据拷贝到temp数组中
{
temp[k++]=right[j++];
}
for(int m=0;m<(left_size+right_size);++m)
{
left[m]=temp[m];//最后的结果存在left数组中
}
}
void meger_sort(int *arr,int len)
{
if(len>1)//递归调用的出口
{
int *left=arr;//left指向数组的首地址
int left_size=len/2;//len/2代表的是数组一半的数据,left_size代表的是左半部分的数据个数
int *right=arr+len/2;//right指向的是右边部分的首元素
int right_size=len-left_size;//右边部分元素的个数
meger_sort(left,left_size);//划分左边,递归左半部分,即左边一直分,直达只有一个元素
meger_sort(right,right_size);//划分右边,递归右半部分,即右边一直分,直到只有一个元素
megering(left,left_size,right,right_size);//归并
}
}
int main()
{
int arr[]={1,8,4,50,4};
int len=sizeof(arr)/sizeof(arr[0]);
meger_sort(arr,len);
for(int i=0;i<len;i++)
{
cout<<arr[i]<<" ";
}
cout<<endl;
}