合并类型排序混乱

时间:2016-10-28 02:47:02

标签: c++ sorting

我被要求写两种类型的合并排序。一种是具有时间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);
}
}

1 个答案:

答案 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)最佳案例性能。