我的合并排序不正确

My merge sort is not ordering correctly

本文关键字:不正确 排序 合并 我的      更新时间:2023-10-16

因此,在一个学校项目中,我被指派根据教授给出的伪代码实现合并排序。这就是我在用例中想到的,而不是订购: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;
    }

我不明白为什么if (i > 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] << " ";