小白的排序学习记录
(四)归并排序
1.思想:使用分治的思想,将要排序的数分组,分完再排,每排完两组就合并这两个数组,不断合并,合并到只有一个数组时就排好了
2.中心代码:递归+循环
3.具体实现:两个函数,一个函数分组,一个函数归并,归并的时候就相当于把两个数组排序了。
(1)实现归并的函数:将传入的两个子数组,分别拷贝到定义的左数组和右数组中,使用插入排序的方法,将两个子数组插入到大数组中,从下标1开始,依次比较两个数组中的元素,假如left[0]>right[0],将right[0]存入大数组array中,0+1,下一次就是left[1]和right[0]比较,依次循环直到某个子数组排完了,若某一个子数组还没排完,就将剩下的直接插在array的后面。
(2)实现分组的函数:找到传入数组的中间数,利用中间数将数组分成两个子数组。计算公式:mid=left+(right-left)/2;
(3)代码
1//此函数用于归并两个子数组,归并的时候就将两个子数组排好了
void merge(int *array, int left, int mid, int right)
{
int left_size=mid-left+1, right_size=right-mid;//子数组分别的大小
int left_array[left_size], right_array[right_size];//定义左右两个数组存储传入的子数组
for(int i=0;i<left_size;i++)//将两个子数组拷贝到,创建的左右子数组中
{
left_array[i]=array[left+i];
}
for(int j=0;j<right_size;j++)
{
right_array[j]=array[mid+1+j];
}
int i=0, j=0, k=left;//分别为左数组,右数组,大数组的循环下标
while(i<left_size&&j<right_size)//插入排序将两个数组插入大数组中 ,左右某一个子数组插入完了,就停止循环
{
if(left_array[i]<=right_array[j])//如果左0<右0,将左0存入大0中
{
array[k]=left_array[i];
i++;//左++,左下一个与右0比较
}
else
{
array[k]=right_array[j];
j++;
}
k++;
}
while(i<left_size)//如果左数组还有没排完的数,直接插在大数组的后面
{
array[k]=left_array[i];
i++;
k++;
}
while(j<right_size)// 如果右数组还有没排完的数,直接插在大数组的后面
{
array[k]=right_array[j];
j++;
k++;
}
}
2//此函数用于分子数组
void merge_sort(int *array, int left, int right)
{
if(left<right)//当数组中只有一个数时不进行排序,和判断是否已经将数组分到了最小,左右重合了,重合了就不需要分了
{
int mid=left+(right-left)/2; //找中间数
merge_sort(array, left, mid);
merge_sort(array, mid+1, right);//分别分为左右两个子数组
merge(array, left, mid, right);//分完后将两个子数组进行归并
}
}
(4)总代码
#include<stdio.h>
#include<stdlib.h>
//此函数用于归并两个子数组,归并的时候就将两个子数组排好了
void merge(int *array, int left, int mid, int right)
{
int left_size=mid-left+1, right_size=right-mid;//子数组分别的大小
int left_array[left_size], right_array[right_size];//定义左右两个数组存储传入的子数组
for(int i=0;i<left_size;i++)//将两个子数组拷贝到,创建的左右子数组中
{
left_array[i]=array[left+i];
}
for(int j=0;j<right_size;j++)
{
right_array[j]=array[mid+1+j];
}
int i=0, j=0, k=left;//分别为左数组,右数组,大数组的循环下标
while(i<left_size&&j<right_size)//插入排序将两个数组插入大数组中 ,左右某一个子数组插入完了,就停止循环
{
if(left_array[i]<=right_array[j])//如果左0<右0,将左0存入大0中
{
array[k]=left_array[i];
i++;//左++,左下一个与右0比较
}
else
{
array[k]=right_array[j];
j++;
}
k++;
}
while(i<left_size)//如果左数组还有没排完的数,直接插在大数组的后面
{
array[k]=left_array[i];
i++;
k++;
}
while(j<right_size)// 如果右数组还有没排完的数,直接插在大数组的后面
{
array[k]=right_array[j];
j++;
k++;
}
}
//此函数用于分子数组
void merge_sort(int *array, int left, int right)
{
if(left<right)//当数组中只有一个数时不进行排序,和判断是否已经将数组分到了最小,左右重合了,重合了就不需要分了
{
int mid=left+(right-left)/2; //找中间数
merge_sort(array, left, mid);
merge_sort(array, mid+1, right);//分别分为左右两个子数组
merge(array, left, mid, right);//分完后将两个子数组进行归并
}
}
int main()
{
int array[]={5, 1, 2, 4, 32, 1};
int size=sizeof(array)/sizeof(array[0]);
merge_sort(array, 0, size-1);
for(int i=0;i<size;i++)
{
printf("%d ", array[i]);
}
return 0;
}