【问题标题】:My merge sort is not ordering correctly我的合并排序没有正确排序
【发布时间】:2014-03-14 19:08:38
【问题描述】:

所以我已经为一个学校项目分配了从教授给出的伪代码实现合并排序。这就是我想出的,在我的用例中, 而不是订购: 0 1 4 5 9 它命令它: 5 4 1 0 9

我的用例: 5 9 1 0 5 4

这里是归并排序的归并部分和全局变量

long long intercambio;
int aux[5555], arr[555];

void merge(int begin, int middle, int end) {
    int i = begin, j = middle+1, k = begin, temp;
    while (i <= middle && j <= end) {
        if (arr[i] < arr[j]) {
            aux[k] = arr[i];
            i++;
        }
        else {
            aux[k] = arr[j];
            j++;
        }
        k++;
        noSwaps++;
    }
    if (i > middle) {
        while (j <= end) {
            if (aux[k -1] > arr[j]) {
                temp = aux[k - 1];
                aux[k - 1] = arr[j];
                aux[k] = temp;
                noSwaps++;
            }
            else {
                aux[k] = arr[j];
            }
            k++;
            j++;
        }
    }
    else {
        while (i <= middle) {
            if (aux[k -1] > arr[i]) {
                temp = aux[k - 1];
                aux[k - 1] = arr[i];
                aux[k] = temp;
                noSwaps++;
            }
            else {
                aux[k] = arr[i];
            }
            k++;
            i++;
        }
    }
}

这里我递归地调用归并排序

void mergeSort(int begin, int end) {
    if (begin < end) {
        int middle = (begin + end) / 2;
        mergeSort(begin, middle);
        mergeSort(middle + 1, end);
        merge(begin, middle, end);
    }
}

这是主类

int main(int argc, const char * argv[])
    {
        int len;

        cin >> len;
        while (len != 0) {

            for (int x = 0; x < len; x++)
                cin >> arr[x];

            noSwaps = 0;

            mergeSort(0, len - 1);
            for (int x = 0; x < len; x++)
                cout << aux[x] << " ";
            cout << endl;

            cout << noSwaps << endl;

            cin >> len;
        }

        return 0;
    }

【问题讨论】:

  • 我认为将代号翻译成英文可以帮助不懂西班牙语的人理解代号
  • 很抱歉。翻译成英文变量名。
  • 正确的翻译是begin , middle , end,而不是start , half , end

标签: c++ sorting merge


【解决方案1】:

我不明白为什么if (i &gt; middle) 块及其else 块中的代码如此复杂。您所要做的就是将剩余的元素复制到aux,然后从aux 复制回arr

void merge(int begin, int middle, int end) {
    int i = begin, j = middle+1, k = begin, temp;
    while (i <= middle && j <= end) {
        // ... same as before ...
    }
    while (i <= middle)
    {
        aux[k++] = arr[i++];
    }
    while (j <= end)
    {
        aux[k++] = arr[j++];
    }
    for (i = begin; i <= end; ++i)
    {
        arr[i] = aux[i];
    }
}

这可能会或可能不会比您的解决方案效率低(或更高),但至少它有效:)

顺便说一句,实现归并排序有一个可爱的技巧,您不必担心先用完一个范围。您将左侧范围按升序复制到aux,将右侧范围按降序复制。然后从两端开始合并,当索引相遇时,两个范围都用完了:

void merge(int begin, int middle, int end)
{
    int i, j, k;
    for (i = begin; i <= middle; ++i)
    {
        aux[i] = arr[i];
    }
    for (j = end; j > middle; --j, ++i)
    {
        aux[i] = arr[j];
    }
    i = begin;
    j = end;
    k = begin;
    while (i <= j)
    {
        arr[k++] = aux[(aux[i] < aux[j]) ? i++ : j--];
    }
}

此解决方案似乎产生了错误的输出,但这仅仅是因为main 内部存在错误:

for (int x = 0; x < len; x++)
    cout << aux[x] << " ";

您正在打印aux,而实际上您应该打印arr

for (int x = 0; x < len; x++)
    cout << arr[x] << " ";

【讨论】:

  • 谢谢,这修复了排序并使实现非常漂亮。但是我还是有一个问题,老师让我们把merge sort中swap的次数尽量少,然后return。使用他的样本输入“5 9 1 0 5 4 0”,交换次数的样本输出为 6。在您的解决方案中,交换次数较高,是否可以保持较低?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-24
  • 1970-01-01
相关资源
最近更新 更多