【问题标题】:I have tried to implement mergesort and am unable to find the exact problem of my code. The program shows no errors but I do not get a desired output我试图实现合并排序,但无法找到我的代码的确切问题。该程序没有显示错误,但我没有得到想要的输出
【发布时间】:2021-08-16 06:19:37
【问题描述】:

尝试实现归并排序,下面是代码。让我知道是否有任何问题。 我的合并功能有什么错误吗?无法指出我的代码中的确切问题。任何有关相同的帮助将不胜感激。

#include <iostream>
using namespace std;

合并两个排序数组的合并函数

void merge(int arr[], int start, int mid, int end) {
    int n1 = mid - start + 1;
    int n2 = end - mid;
    
    int arr1[n1], arr2[n2];
    for (int i = 0; i < n1; i++) {
        arr1[i] = arr[start + i];
    }
    for (int j = 0; j < n2; j++) {
        arr2[j] = arr[mid + 1 + j];
    }

    int i;
    int j;
    int p;
    i = 0;
    j = 0;
    p = start;
    
    while (i < n1 && j < n2) {
        if (arr1[i] <= arr2[j]) {
            arr[p] = arr1[i];
            i++;
        } else {
            arr[p] = arr2[j];
            j++;
        }
        p++;
    }
    while (i < n1) {
        arr[p] = arr1[i];
        i++;
        p++;
    }

    while (j < n2) {
        arr[p] = arr2[j];
        i++;
        p++;
    }
}

递归调用归并排序

void merge_sort(int arr[], int start, int end) {
    if (start >= end) {
      return;
    }
    if (start < end) {
        int mid = start + (end - 1) / 2;
        merge_sort(arr, start, mid);
        merge_sort(arr, mid + 1, end);
        merge(arr, start, mid, end);
    }
}

打印数组的打印函数

void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++)
        cout << arr[i] << " ";
    cout << endl;
}

主要功能

int main() {
    int arr[] = { 6, 5, 12, 10, 9, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
    
    merge_sort(arr, 0, n - 1);
    cout << "The sorted array is: " << endl;
    printArray(arr, n);
}

【问题讨论】:

  • 在递归函数中自动分配任意大小的数组(例如int arr1[n1], arr2[n2];)是堆栈溢出的秘诀。即使大小已知,在递归函数中自动分配数组也可能是不确定的,但至少您可以在存储空间用完之前预先计算可以处理的最大深度。也就是说,数组中有六个元素,你可能是安全的。
  • 根据 gdb,arr[p] = arr2[j]; p 到达 262272。可能想了解一下这是怎么发生的。看起来它可能与while (j &lt; n2) 有关,并且循环内没有任何东西改变j 的值。 i++; -> j++;?顺便说一句,这就是为什么我讨厌-讨厌-讨厌单字母变量名的原因。
  • 提示:在 C++ 中,使用 std::vector 表示可变长度数组。
  • your Rubber duck讨论int mid = start + (end - 1) / 2;

标签: c++ recursion mergesort


【解决方案1】:

代码有2个错误:

  • 将中点计算为int mid = start + (end - 1) / 2; 是不正确的。你应该写:

      int mid = start + (end - start) / 2;
    
  • merge 的最后一个循环中,您递增i 而不是j。请注意,此循环是多余的,因为 arr2 的其余元素已经在 arr 的末尾。

您遵循合并排序实现中的经典约定,其中end 是切片中最后一个元素的索引。这个约定需要多次+1/-1调整,很容易出错。

在数组索引从0 开始的C 和相关语言中,使用不同的约定更为惯用:将start 作为切片的第一个元素的索引,将end 作为刚刚过去的索引最后一个元素。这允许指定空拼接并产生更清晰的代码。

这是修改后的版本:

#include <iostream>

using namespace std;

// Merge function to merge the two sorted arrays
void merge(int arr[], int start, int mid, int end) {
    int n1 = mid - start;
    int n2 = end - mid;
    int arr1[n1], arr2[n2];

    for (int i = 0; i < n1; i++) {
        arr1[i] = arr[start + i];
    }
    for (int j = 0; j < n2; j++) {
        arr2[j] = arr[mid + j];
    }

    int i = 0;
    int j = 0;
    int p = start;
    
    while (i < n1 && j < n2) {
        if (arr1[i] <= arr2[j]) {
            arr[p] = arr1[i];
            i++;
        } else {
            arr[p] = arr2[j];
            j++;
        }
        p++;
    }
    while (i < n1) {
        arr[p] = arr1[i];
        i++;
        p++;
    }
    // the remaining elements from `arr2` are already in place in `arr`
}

// Calling mergesort recursively
void merge_sort(int arr[], int start, int end) {
    if (end - start > 1) {
        int mid = start + (end - start) / 2;
        merge_sort(arr, start, mid);
        merge_sort(arr, mid, end);
        merge(arr, start, mid, end);
    }
}

// Print function to print the array
void printArray(const int arr[], int size) {
    for (int i = 0; i < size; i++)
        cout << arr[i] << " ";
    cout << endl;
}

// Main function
int main() {
    int arr[] = { 6, 5, 12, 10, 9, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
    
    merge_sort(arr, 0, n);
    cout << "The sorted array is: " << endl;
    printArray(arr, n);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多