目录
一、排序思想
该算法是采用分治法,将已有序的子序列合并,得到完全有序的序列。即先使每个子序列有序,再使最终序列有序。
二、排序过程
1、对无序数组进行递归分解(这里只是递归中的递推过程)
2、归并:将两个区间数据进行逐一比较,较小的尾插进新数组(这里是递归中的回归)
注:
1、所有的递归分解完成后才开始回归归并(即要分解到最小区间)
2、子区间排序过程其实是在比较尾插环节完成,一直归并到完整数组才完成最终排序
3、如下图解以及代码实现都是排成升序
三、代码实现
1、递归写法
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//打印
void Print(int* a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
//归并子函数
void _MergeSort(int* a, int begin, int end, int* tmp)
{
if (begin >= end)
{
return;
}
int mid = (begin + end) / 2;
//递归排序
//[begin,mid] [mid+1,end]
_MergeSort(a, begin, mid, tmp);
_MergeSort(a, mid+1, end, tmp);
//递归中递推过程完成,开始回归归并
int begin1 = begin, end1 = mid;
int begin2 = mid + 1, end2 = end;
int i = begin;
while (begin1 <= end1 && begin2 <= end2)//闭区间
{
//逐一比较,小的尾插进tmp
if (begin1 < begin2)
{
tmp[i++] = a[begin1++];
}
else
{
tmp[i++] = a[begin2++];
}
}
//到此有一组归并完成,有一组可能没有完成,但不知是哪一组
//暴力排除
while(begin1 <= end1)
{
tmp[i++] = a[begin1++];
}
while(begin2 <= end2)
{
tmp[i++] = a[begin2++];
}
//拷贝(并非一次性拷贝,而是分段拷贝,递归的每一次回归都拷贝一次)
//每一次回归拷贝过程的区间可能都不同,begin、end是变化的,如下的begin不可少
memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}
//归并
void MergeSort(int* a, int n)
{
int* tmp = (int*)malloc(n * sizeof(int));
if (tmp == NULL)
{
perror("malloc fail");
exit(-1);
}
_MergeSort(a, 0, n - 1, tmp);
free(tmp);
tmp = NULL;
}
int main()
{
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
MergeSort(arr, 10);
Print(arr, 10);
return 0;
}
2、非递归写法
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//打印
void Print(int* a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
//归并------非递归
void MergeSortNonR(int* a, int n)
{
int* tmp = (int*)malloc(n * sizeof(int));
if (tmp == NULL)
{
perror("malloc fail");
return;
}
int gap = 1;//gap是区间跨度
while (gap < n)
{
//一层归并,遍历
for (int i = 0; i < n; i += gap * 2)
{
int begin1 = i, end1 = i + gap - 1;//区间1
int begin2 = i + gap, end2 = i + 2 * gap - 1;//区间2
//避免越界,修正
if (end1 >= n || begin2 >= n)
{
break;
}
if (end2 >= n)
{
end2 = n - 1;
}
//开始归并
int j = i;
while (begin1 <= end1 && begin2 <= end2)
{
if (begin1 < begin2)
{
tmp[j++] = a[begin1++];
}
else
{
tmp[j++] = a[begin2++];
}
}
while (begin1 <= end1)
{
tmp[j++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[j++] = a[begin2++];
}
//拷贝(归并一部分拷贝一部分)
memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));
}
gap = gap * 2;
}
free(tmp);
tmp = NULL;
}
int main()
{
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
MergeSortNonR(arr, 10);
Print(arr, 10);
return 0;
}
感谢阅读,本文如有疏漏不当之处,烦请各位指正。