介绍
思路:将两个有序的数组归并到一个更大的有序数组中。
原理:按照一定规则,将数组不断分割到最小单位进行排序,然后将结果归并。直到合并回原本数组长度。
特性:需要使用额外的空间。
思想:分治思想(分割大问题为一个个小问题,通过解决所有的小问题从而解决大问题)
实现:自顶向下,自底向上
环境:适用数据量较大的数据
建议
接下来的算法会涉及递归,建议一边看示意图一边自己实现下流程,对照着学习会记忆更深刻。
后续代码源于书籍《算法》
实现
原地归并
无论哪种归并排序的实现,都需要进行数据对比并归并。而原地归并就是实现这个逻辑。
单纯直接使用原地并归并不能使数组有序排序,而是要按规则多次使用才能得到有序数组。
逻辑:分别有两个对象指向头和中间+1的位置。循环从头开始,头尾对比后赋值当前指向对象,按照规则其中一个指向向前移动。循环直到尾为结束。
记忆点:头尾对比后,赋值当前。
void merge(int a[], int low, int mid, int height)
{
int index = low;
int j = mid + 1;
for (int k = low; k <= height; k++) {
aux[k] = a[k];
}
for (int k = low; k <= height; k++)
{
if (index > mid)
{
a[k] = aux[j++];
}
else if(j > height)
{
a[k] = aux[index++];
}
else if (less(aux[j], aux[index]))
{
a[k] = aux[j++];
}
else
{
a[k] = aux[index++];
}
}
}
自顶向下
逻辑:递归将数组分为左右两个数组,从最小单位开始排序。排序后返回继续排序,直到回归整个数组。
记忆点:递归分组
解释:数组从大到小分组。从最小的数组开始有序,渐渐到大的数组有序。
void sort(int* a, int low, int height)
{
if (height <= low)
{
return;
}
int mid = low + (height - low) / 2;
sort(a, low, mid);
sort(a, mid + 1, height);
merge(a, low, mid, height);
}
自底向上
逻辑:定义间隔值,将数组按间隔值分组,排序后,间隔值增加。直到间隔值为数组值。
记忆点:间隔分组
解释:数组从小到大分组。通过小部分有序,不断重新排序得到大的有序数组。
void sort(int* a, int length)
{
for (int sz = 1; sz < length; sz = sz + sz)
{
for (int low = 0; low < length - sz; low += sz + sz)
{
int mid = low + sz - 1;
int curLength = min(low + sz + sz - 1, length - 1);
merge(a, low, mid, curLength);
}
}
}