合并排序不起作用?

时间:2015-09-17 18:55:25

标签: c++ algorithm sorting mergesort

我在使用Merge Sort功能时遇到了一些麻烦,因为我的教授给出了我的规范。一直在盯着VS和谷歌寻找这个家伙的永恒。

算法提供:

enter image description here

arrayFunctions.h

template<class T>
void printArray(T arr[], int numElements)
{
    cout << "(";

    for (int i = 0; i < numElements; i++)
    {

        cout << arr[i];

        if (i < numElements - 1)
            cout << ", ";
    }

    cout << ")" << "\n\n";
}

template <class T>
void setArray(T to[], T from[], int size)
{
    for (int i = 0; i < size; i++)
        to[i] = from[i];
}

template <class T>
void setArray(T to[], T from[], int size1, int size2)
{
    int size = size1;
    if (size2 < size1) size = size2;

    setArray(to, from, size);
}

const int NUM = 5;

int originalArray[NUM] = { 4, 2, 5, 3, 1 };
int newArray[NUM];

cout << "Original:\n";
printArray(originalArray, NUM); //prints an array with formatting

// Merge Sort
setArray(newArray, originalArray, NUM); //set's newArray to the same values of originalArray
mergeSort(newArray, 0, NUM - 1);

cout << "Merge Sort:\n";
printArray(newArray, NUM);

pause();

运行main时的输出是:

原件: (4,2,5,3,1)

合并排序: (0,0,0,-33686019,1)

合并:

template <class T>
void merge(T L[], int lowerBound, int mid, int upperBound)
{
    // Get size for new arrays
    int size1 = mid - lowerBound;
    int size2 = upperBound - mid;

    // Create Temporary Arrays
    T * tmp1 = new T[size1 + 1]();
    T * tmp2 = new T[size2 + 1]();


    // Populate both arrays from original
    for (int i = 0; i < size1; i++)
        tmp1[i] = L[lowerBound + i];

    for (int j = 0; j < size2; j++)
        tmp2[j] = L[mid + j];

    tmp1[size1] = numeric_limits<T>::max();
    tmp2[size2] = numeric_limits<T>::max();

    int i = 0;
    int j = i;

    for (int k = lowerBound; k < upperBound; k++)
    {
        if (tmp1[i] <= tmp2[j])
        {
            L[k] = tmp1[i];
            i++;
        }
        else
        {
            L[k] = tmp2[j];
            j++;
        }
    }

    delete[] tmp1;
    delete[] tmp2;
}

归并:

template<class T>
void mergeSort(T L[], int lowerBound, int upperBound)
{
    if (lowerBound < upperBound)
    {
        int mid = (lowerBound + upperBound) / 2;

        mergeSort(L, lowerBound, mid);
        mergeSort(L, mid + 1, upperBound);

        merge(L, lowerBound, mid, upperBound);
    }
}

那么......我做错了什么?正确方向的碰撞将非常受欢迎。

5 个答案:

答案 0 :(得分:3)

这是一个简单的错误。

T * tmp1 = new T[size1 + 1]();
...
tmp1[size1 + 1] = numeric_limits<T>::max();
           ^^^

数组索引从0转到n-1,而不是n

答案 1 :(得分:2)

// tmp1[size1 + 1] = (infinity?)
// tmp2[size2 + 1] = (infinity?)

这是破坏你的合并的代码的一部分,想想如果你有两个列表,然后他们应该有两个列表会发生什么,请参阅:

// Create Temporary Arrays
T * tmp1 = new T[size1 + 1]();
T * tmp2 = new T[size2 + 1]();

这意味着他们可能看起来像这样的2个值

foo = [1,2,?]
bar = [3,4,?]

问号将是一些数字,但你无法知道什么,如果你然后在循环内运行几次比较你会得到让我们说 i = 2,j == 0 为简单起见,现在您尝试进行比较:

if (foo[2] <= bar[0])

相同
if (? <= 3)

意味着你有一个未定义的行为,更糟糕的是你可能会去 i = 3 并开始查看随机内存。 总而言之,(无穷大?)以某种聪明的方式。

答案 2 :(得分:1)

在C ++合并函数中,L []的右半部分以mid + 1开头,因此第二个填充循环应为:

    for (int j = 0; j < size2; j++)
        tmp2[j] = L[mid + j + 1];

在提供的算法中,索引从1到n,因此第一个填充循环是TMP1 [i]←L [lowerBound + i - 1]。使用C ++,索引从0到n-1,因此C ++首先填充循环:tmp1 [i] = L [lowerBound + i];是正确的,但第二个循环需要改为tmp2 [j] = L [mid + j + 1];

答案 3 :(得分:1)

很抱歉忘记回复近两周:/

这是一个错误,但我跟踪它们并使其正常工作。 感谢所有帮助过的人。

更改

int size1 = mid - lowerBound;
int size2 = upperBound - mid;

int size1 = mid - lowerBound + 1;
int size2 = upperBound - mid;

更改

for (int j = 0; j < size2; j++)
    tmp2[j] = L[mid + j];

for (int j = 0; j < size2; j++)
    tmp2[j] = L[mid + j + 1];

更改

for (int k = lowerBound; k < upperBound; k++)
{
    if (tmp1[i] <= tmp2[j])
    {
        L[k] = tmp1[i];
        i++;
    }
    else
    {
        L[k] = tmp2[j];
        j++;
    }
}

for (int k = lowerBound; k <= upperBound; k++)
{
    if (tmp1[i] <= tmp2[j])
    {
        L[k] = tmp1[i];
        i++;
    }
    else
    {
        L[k] = tmp2[j];
        j++;
    }
}

答案 4 :(得分:0)

问题1:Sentinels

被注释掉的

infinity是其中一个问题。

// tmp1[size1] = (infinity?)
// tmp2[size2] = (infinity?)

它被用作哨兵,所以当你到达tmp1(或tmp2)的最后一个位置时,它会确保你复制另一个数组中的所有其他元素,{{ 1}}(或tmp2)。您可以使用tmp1在此处代表inf

@Petter很好地描述了这个问题发生的原因。

问题2:初始化

在合并数组之前,您的其他问题似乎是在初始化中:

std::numeric_limits<T>::max()

伪代码是从int i = 1; int j = i; 建立索引,而它应该从1开始。

问题3:索引

正如@MarkRansom所指出的,索引范围应该从00,而不是size1

size1 + 1
相关问题