【问题标题】:What's the issue in this merge sort algorithm in c++c ++中的这种合并排序算法有什么问题
【发布时间】:2021-01-30 05:26:08
【问题描述】:

我从 gfg 课程中学到了这一点,即使他们为代码提供的链接与我编写的代码相似,但仍然无法找到问题所在:

#include <iostream>
#include <algorithm>

using namespace std;

void merge(int a[], int low, int mid, int high) {
    int m = mid - low + 1, n = high - mid;
    int left[m], right[n];
    for (int i = 0; i < m; i++) {
        left[i] = a[low + i];
    }
    for (int j = 0; j < n; j++) {
        right[j] = a[m + j];
    }
    int i = 0, j = 0, k = low;
    while (i < m && j < n) {
        if (left[i] <= right[j]) {
            a[k] = left[i];
            i++;
            k++;
        } else {
            a[k] = right[j];
            j++;
            k++;
        }
    }
    while (i < m) {
        a[k] = left[i];
        i++;
        k++;
    }
    while (j < n) {
        a[k] = right[j];
        j++;
        k++;
    }
}

void mergeSort(int arr[], int l, int r) {
    if (l >= r) {
        return;
    }
    if (r > l) {
        int m = l + (r - l) / 2;
        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);
        merge(arr, l, m, r);
    }
}

int main() {
    int n;
    cout << "enter size of array: ";
    cin >> n;
    int arr[n];
    cout << "enter element in array: ";
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }
    mergeSort(arr, 0, n - 1);
    cout << "array after sort: \n";
    for (int i = 0; i < n; i++) {
        cout << arr[i] << " ";
    }
    return 0;
}

这里是以{10,5,30,15,7} 提供输入的代码,它以{5,10,10,15,30} 返回输出

Here is the output screen shot for reference

【问题讨论】:

  • 在调试器中单步执行代码会揭示什么?
  • 您的程序不是有效的 C++ 程序,因为 C++ 没有 variable-length arrays。请改用std::vector。并请some good books 正确学习 C++。
  • @Someprogrammerdude 我有好书我认为你没有正确阅读标题如果只是在 C++ 中搜索合并排序,你只会得到这种类型的解决方案,而不是向量解决方案。我想知道这段代码不工作的原因,没有忽略和以其他方式实现,但无论如何谢谢
  • 仅仅因为许多没有经验的程序员使用的东西并不意味着它是好的,甚至是正确的。您的论点类似于“如果每个人都跳下悬崖,我也会”的整个论点。阅读你的书,养成良好的习惯,学会识别坏事(现在大多数东西都来自所谓的“竞争”网站),最重要的是不要盲目复制,还要为自己思考。
  • 至于你代码的问题,调试调试调试。知道如何调试代码以及​​如何使用调试器几乎(如果不是更重要的话)比了解语言更重要。这是所有程序员的一项关键技能。

标签: c++ algorithm sorting mergesort


【解决方案1】:

您将 m 变量(左侧数组的大小)与 mid(左侧数组中的最后一个索引)混淆了

而不是这个:

for(int j=0;j<n;j++){
    right[j] = a[m+j];
}

这个:

for (int j = 0; j < n; j++) {
    right[j] = a[mid + j + 1];
}

专业提示:一个字母的变量可以作为 for 循环中的索引。但是对于其他任何事情,请给名称一个明显的含义。例如,不要将mn 命名为leftArraySizerightArraySize。将它们命名为 firstIndexlastIndex,而不是 lr。当您使用名称有意义的钝变量名称时,错误在哪里会很明显。

【讨论】:

  • 非常感谢您相应地更改变量名称,是的,我很困惑,这就是它不引人注目的原因。谢谢你,我会记住未来的。
【解决方案2】:

代码中的错误在right的初始化循环中:a[m + j]应该是a[mid + j + 1]

但请注意,复制数组的右半部分是不必要的,因为这些元素在最终被覆盖之前已被复制。

merge 函数可以简化为:

void merge(int a[], int low, int mid, int high) {
    int m = mid - low + 1;
    int left[m];
    for (int i = 0; i < m; i++) {
        left[i] = a[low + i];
    }
    int i = 0, j = mid + 1, k = low;
    while (i < m && j <= high) {
        if (left[i] <= a[j]) {
            a[k] = left[i];
            i++;
            k++;
        } else {
            a[k] = a[j];
            j++;
            k++;
        }
    }
    while (i < m) {
        a[k] = left[i];
        i++;
        k++;
    }
}

另请注意,所有这些+1 / -1 调整都令人困惑且容易出错。您可以通过传递high 作为要排序的切片之外的元素的索引和传递mid 右半部分的第一个元素的索引来简化代码。命名变量l 也容易出错,因为l 看起来与1 很相似。

这里是修改后的代码:

#include <iostream>
#include <algorithm>

using namespace std;

void merge(int a[], int low, int mid, int high) {
    int m = mid - low;
    int left[m];
    for (int i = 0; i < m; i++) {
        left[i] = a[low + i];
    }
    int i = 0, j = mid, k = low;
    while (i < m && j < high) {
        if (left[i] <= a[j]) {
            a[k++] = left[i++];
        } else {
            a[k++] = a[j++];
        }
    }
    while (i < m) {
        a[k++] = left[i++];
    }
}

void mergeSort(int arr[], int low, int high) {
    if (high - low >= 2) {
        int mid = low + (high - low) / 2;
        mergeSort(arr, low, mid);
        mergeSort(arr, mid, high);
        merge(arr, low, mid, high);
    }
}

int main() {
    int n;
    cout << "enter size of array: ";
    cin >> n;
    int arr[n];
    cout << "enter element in array: ";
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }
    mergeSort(arr, 0, n);
    cout << "array after sort: \n";
    for (int i = 0; i < n; i++) {
        cout << arr[i] << " ";
    }
    cout << "\n";
    return 0;
}

merge 函数可以进一步简化为:

void merge(int a[], int low, int mid, int high) {
    int m = mid - low;
    int left[m];
    for (int i = 0; i < m; i++) {
        left[i] = a[low + i];
    }
    int i = 0, j = mid, k = low;
    while (i < m) {
        if (j >= high || left[i] <= a[j]) {
            a[k++] = left[i++];
        } else {
            a[k++] = a[j++];
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    • 2012-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多