我被要求写两种类型的合并排序。一种是具有时间theta(n lgn)的二元合并排序和具有时间O(n lgn)的自然合并排序。我到处搜索,了解他们每个人做了什么。我无法理解这些差异,我只需要一些解释或者例子会很棒。我写了一个合并排序,但我有的是自然或二进制合并排序?
bool compareElements(int i, int j)
{
++COMPARE_COUNT;
//int *t = i;
return i < j;
}
void merge(int values[], int left[], int right[], int middle, int total)
{
int left_size = middle, right_size = total - middle;
int i = 0, j = 0;
// Loop through values array
for (int k = 0; k < total; k++)
{
// If elements left on left and either no elements on right
// or left is larger than right, then use next left value
if (i < left_size && (j >= right_size || left[i] <= right[j]))
{
values[k] = left[i];
i++;
}
// else use next right value
else
{
values[k] = right[j];
j++;
}
}
}
void mergeSort(int values[], int n,bool result)
{
if(result == false)
{
if (n < 2)
{
return;
}
int middle = n / 2;
int *left = new int [middle];
int *right = new int [n - middle];
for (int i = 0; i < n; i++)
{
//COMPARE_COUNT++;
if(compareElements(i,middle)) //(i < middle)
{
SWAP_COUNT++;
left[i] = values[i];
}
else if(!compareElements(i,middle))
{
SWAP_COUNT++;
right[i - middle] = values[i];
}
}
mergeSort(left, middle,result);
mergeSort(right, n - middle,result);
merge(values, left, right, middle, n);
}
}
答案 0 :(得分:4)
二进制合并排序有一个非常简单的递归定义:将输入数组拆分为两半,使用二进制合并排序对两半进行排序,将两半合并为一个排序序列。这就是你实施的目标。
另一个版本是自下而上合并排序。首先将序列拆分为长度为1的子序列,然后开始合并它们。
自然合并排序具有不同的第一个步骤。它不会将输入序列分成两半,而是分成运行。运行是一系列增加或减少的元素。例如,以下数组:
0 1 4 2 3 9 8 7 5 2 1 3 4 2 4 3 4
可以拆分成这样的运行:
0 1 4 | 2 3 9 | 8 | 7 | 5 | 2 | 1 3 4 | 2 4 | 3 4
每次跑步的位置都在提升。然后开始合并运行,就像合并排序一样,除了从底部向上合并 。
这称为自然合并排序的原因是,如果您的输入已经(部分)预先排序,则算法将开始接近O(n)最佳案例性能。