【问题标题】:Sort array using merge sort使用归并排序对数组进行排序
【发布时间】:2021-05-02 15:41:06
【问题描述】:

我正在使用归并排序来对我的数组进行降序处理。我的第一个元素改变了他的值的原因是什么? 我的一半代码有效。但是我的第一个和最后一个元素出了点问题。

#include <iostream>

void Merge(int a[], int low, int high, int mid)
{
    int i = low, j = mid + 1, k = 0;
    int temp[high - low + 1];

    while (i <= mid && j <= high) {
        if (a[i] > a[j])
            temp[k++] = a[i++];

        else
            temp[k++] = a[j++];
    }

    while (i <= mid) {
        temp[k++] = a[i++];
    }

    while (j <= high) {
        temp[k++] = a[j++];
    }
    for (i = low; i <= high; i++) {
        a[i] = temp[i - low];
    }
    return;
}

void MergeSort(int a[], int low, int high)
{
    int mid;
    if (low < high) {
        mid = (low + high) / 2;
        MergeSort(a, low, mid);
        MergeSort(a, mid + 1, high);

        Merge(a, low, high, mid);
    }

    return;
}

void output(int* a, int n)
{
    for (int i = 0; i < n; i++) {
        std::cout << a[i] << "\t";
    }
}

int main()
{
    int n;
    std::cin >> n;
    int a[n];
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    MergeSort(a, 0, n);
    output(a, n);
}

输出必须是这个。

输入 10

1 2 3 4 5 6 7 8 9 10

输出

10 9 8 7 6 5 4 3 2 1

但我明白了 输出

4197055 10  9   8   7   6   5   4   3   2 

我是 C++ 的初学者。所以如果你能帮助我在这里完成我的第一步,我会很高兴。

【问题讨论】:

  • 此代码似乎工作,无法重现。 godbolt.org/z/nPqhn3
  • @foragerDev 不,它不起作用godbolt.org/z/G9GPnv 未定义行为的经典示例。 (带有 gcc 的 godblot 能够显示行号:godbolt.org/z/1M7vrj
  • @MarekR 在我的机器上,我不明白。
  • @foragerDev 再次这是未定义的行为,因此它可能会崩溃它可能什么都不做它可能会打印 tash。请注意,唯一的区别是我启用了地址清理程序。
  • 您将n 传递为high。但是n 比最高元素的索引高一个,这会导致未定义的行为。 MergeSort(a,0,n-1); 将解决问题。

标签: c++ sorting merge conditional-statements output


【解决方案1】:

更改此行:Merge(a, low, high-1, mid);,因为您使用的是从零开始的索引

更新:之前的更改不适用于所有情况。

仅尝试此更改:MergeSort(a, 0, n-1)

尽量使用从 1 开始的索引来避免这种情况

【讨论】:

【解决方案2】:

您混淆了索引范围的描述方式。在相同的情况下,您使这些范围在最后关闭,而在其他情况下在最后打开。结果是未定义的行为缓冲区溢出。

这里是固定版本,其中low 指向第一个元素,high 指向最后一个元素之外的一步。

请记住,在 C++ 中,数组 arr[n] 的索引应该从 0n - 1(含)。

void Merge(int a[], int low, int high, int mid)
{
    int i = low, j = mid, k = 0;
    int temp[high - low];

    while (i < mid && j < high) {
        temp[k++] = a[i] < a[j] ? a[i++] : a[j++];
    }

    while (i < mid) {
        temp[k++] = a[i++];
    }

    while (j < high) {
        temp[k++] = a[j++];
    }

    for (i = low; i < high; i++) {
        a[i] = temp[i - low];
    }
    return;
}

void MergeSort(int a[], int low, int high)
{
    int mid;
    if (low + 1 < high) {
        mid = (low + high) / 2;
        MergeSort(a, low, mid);
        MergeSort(a, mid, high);

        Merge(a, low, high, mid);
    }

    return;
}

https://godbolt.org/z/nET5YT

【讨论】:

    【解决方案3】:
     #include <iostream>
        using namespace std;
        void merge(int arr[], int l, int m, int r)
        {
            int n1 = m - l + 1;
            int n2 = r - m;
         
            int L[n1], R[n2];
        
            for (int i = 0; i < n1; i++)
                L[i] = arr[l + i];
            for (int j = 0; j < n2; j++)
                R[j] = arr[m + 1 + j];
        
            int i = 0;
         
            int j = 0;
        
            int k = l;
         
            while (i < n1 && j < n2) {
                if (L[i] <= R[j]) {
                    arr[k] = L[i];
                    i++;
                }
                else {
                    arr[k] = R[j];
                    j++;
                }
                k++;
            }
         
            while (i < n1) {
                arr[k] = L[i];
                i++;
                k++;
            }
        
            while (j < n2) {
                arr[k] = R[j];
                j++;
                k++;
            }
        }
         
        void mergeSort(int arr[],int l,int r){
            if(l>=r){
                return;
            }
            int m = (l+r-1)/2;
            mergeSort(arr,l,m);
            mergeSort(arr,m+1,r);
            merge(arr,l,m,r);
        }
        
        void output(int A[], int size)
        {
            for (int i = size - 1; i >= 0; i--)
                cout << A[i] << " ";
        }
        
        int main()
        {
            int arr[] = { 1, 2, 3, 5, 6, 7 };
            int arr_size = sizeof(arr) / sizeof(arr[0]);
         
            mergeSort(arr, 0, arr_size - 1);
         
            output(arr, arr_size);
            return 0;
        }
    

    【讨论】:

    • 尝试使用 cmets 引导用户完成您的解决方案。
    最近更新 更多