简体   繁体   English

合并排序错误的输出

[英]merge sort incorrect output

I'm trying to use the following merge sort function to sort an array. 我正在尝试使用以下合并排序功能对数组进行排序。 However it is not giving me the expected output. 但是,它没有给我预期的输出。 It will not print out correct/expected output ie 它不会打印出正确/预期的输出,即

Input: 5,4,3,2,1 输入:5、4、3、2、1
Output: 1,2,3,4,5 输出:1,2,3,4,5

Instead it gives: 2,3,4,5,1,9,8,7,8,4,1,8,8,2. 相反,它给出:2,3,4,5,1,9,8,7,8,4,1,8,8,2。

#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>

using namespace std;

void mergeSort(int a[], int low , int high,int res[]);
void merge(int a[], int low , int mid , int high,int res[]);
void mergeSort(int numbers[], int temp[], int array_size);

const int SIZE=5;

int main () {

    int sorted[SIZE];
    for (int i=0; i<SIZE; i++) {
        cout << "input numbers" <<endl;
        cin >>sorted[i];
    }
    int merge[SIZE];

    mergeSort(sorted,merge,SIZE);

    for (int i=0; i<SIZE; i++) {
        cout << merge[i];
    }

    return 0;
}

void mergeSort(int numbers[], int temp[], int array_size)
{
    mergeSort(numbers, 0, array_size-1, temp);
}

void mergeSort(int a[], int low , int high,int res[])
{
    int mid = (low + high)  /2;
    if (low + 1 < high)
    {
        //  Sort sub-parts
        mergeSort(a,low,mid,res);
        mergeSort(a,mid,high,res);

        //  Merge back to "res"
        merge(a,low,mid,high,res);
    }else{
        res[low] = a[low];
    }
}

void merge(int a[], int low , int mid , int high,int res[])
{
    int i = low;
    int j = mid;
    int k = low;   //  Use "low" instead of 0.

    while (i < mid && j < high)
        if(a[i] < a[j])
            res[k++] = a[i++];
        else
            res[k++] = a[j++];

    while (i < mid)
        res[k++] = a[i++];

    while (j < high)
        res[k++] =a[j++];

    //  Copy back to "a"
    for (int c = low; c < high; c++){
        a[c] = res[c];
    }
}

I think this is causing the problem -- 我认为这是造成问题的原因-

    //  Sort sub-parts
    mergeSort(a,low,mid,res);
    mergeSort(a,mid,high,res);

It should be 它应该是

    //  Sort sub-parts
    mergeSort(a,low,mid,res);
    mergeSort(a,mid+1,high,res);

Also if (low + 1 < high) should be changed to if (low < high) 同样将if (low + 1 < high)更改为if (low < high)

Furthermore while (i < mid && j < high) should be while (i <= mid && j <= high) and single while loops below it too need to be updated with <= 此外, while (i < mid && j < high)应该是while (i <= mid && j <= high)并且低于它的单个while循环也需要用<=更新

There is a bit of confusion in your handling of indexing limits. 在处理索引限制时会有些混乱。

Two very common ways to represent ranges are: 表示范围的两种非常常见的方法是:

  1. range limits are pointing between elements 范围限制指向元素之间
  2. range limits are pointing to elements 范围限制指向元素

范围坐标系

In the picture the numbering above is using the "pointing between elements" approach and the grayed out range is (2, 5) . 在图片中,上面的编号使用的是“元素之间的指向”方法,灰色范围是(2, 5)

The numbering below is instead using the "pointing to elements" approach and the same range is (2, 4) . 下面的编号改为使用“指向元素”方法,并且相同的范围是(2, 4)

As a personal preference I like the "between elements" approach much more: for example the size of a range is high-low and you can represent easily empty ranges or even inverted ranges. 作为个人喜好,我更喜欢“元素之间”的方法:例如,范围的大小是high-low ,您可以轻松地表示空范围甚至是倒置范围。 The important thing is however that you keep always clear in your mind if you're using the first or the second approach when writing code that is managing ranges. 但是重要的是,在编写用于管理范围的代码时,如果要使用第一种或第二种方法,请始终牢记。

In your code there's that kind of confusion; 在您的代码中有这种混乱。 for example in mergesort you are checking if 例如在mergesort您正在检查是否

low + 1 < high

and this means that you're using the "between elements" approach because when high - low = 1 means there is only one element and no sorting is needed. 这意味着您正在使用“元素间”方法,因为当high - low = 1意味着只有一个元素,不需要排序。 Also you recurse passing (low, mid) and (mid, high) : another clear sign that the "between elements" approach is used because you surely don't want to move around array[mid] twice. 另外,您递归传递(low, mid)(mid, high) :另一个明显的信号是使用了“元素之间”方法,因为您肯定不想在array[mid]周围移动两次。

In the same code however you're passing the function 0 and array_size-1 in the main program, a clear sign that in this case you're using the "pointing to elements" approach instead. 但是,在同一代码中,您要在array_size-1传递函数0array_size-1 ,这清楚地表明在这种情况下,您使用的是“指向元素”方法。

Just double-check that all your index and range usage is coherent and the code will be fine. 只需仔细检查所有索引和范围用法是否一致,代码就可以了。

According to your sample code, only 5 numbers should be printed as result (because of const int SIZE=5 ). 根据您的示例代码,结果仅应打印5个数字(因为const int SIZE = 5 )。

That aside, note that you provide the position of the last element of your list as "high" parameter. 除此之外,请注意,您将列表的最后一个元素的位置作为“ high”参数提供。

However, in your merge function, your while(j < high) conditions make sure that this last element in the list will not be sorted, because sorting stops just before reaching it. 但是,在合并函数中, while(j <high)条件可确保不会对列表中的最后一个元素进行排序,因为排序会在到达它之前停止。

Update: The for loop at the end of the merge function needs to be adapted to also copy the last ("high") element back into the array a . 更新:合并功能末尾的for循环需要进行调整,以将最后一个(“高”)元素也复制回数组a中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM