【问题标题】:I keep losing the values and getting 0's. What's the wrong with my logic?我不断失去价值并得到0。我的逻辑有什么问题?
【发布时间】:2016-02-21 21:55:58
【问题描述】:

大家好,我需要在 C++ 中使用给定的 mergeSort() 标头编写合并排序;

我的分区是正确的,但它合并了一个在它有 0 之前合并的数组。例如:如果我有 [34][21] 我得到 [21, 34] 但是当它与假设 [8] 合并时它给出 [0, 0, 8]。我正在失去价值。请帮我调试一下。


注意: 我有一些 moveCount 来计算数据移动和 compCount 来计算计算。请不要与这些混淆。

int * merge(int * left ,int szLeft ,int * right,int szRight, int &compCount, int &moveCount){
    int * newArr = new int [szLeft+szRight];
    cout << "Left: ";
    for (int i = 0; i < szLeft; ++i){
        cout << left[i] << " ";
    }
    cout << endl;

    cout << "Right: ";
    for (int i = 0; i < szRight; ++i){
        cout << right[i] << " ";
    }
    cout << endl;

    int bigArrIndex = 0, rightArrIndex = 0,leftArrIndex = 0;

    while(leftArrIndex < szLeft && rightArrIndex < szRight){
        compCount++;
        if(right[rightArrIndex] <= left[leftArrIndex]){
            newArr[bigArrIndex] = right[rightArrIndex];
            rightArrIndex++;
            compCount++;
        }
        else{
            newArr[bigArrIndex] = left[leftArrIndex];
            leftArrIndex++;
        }
        moveCount++;
        bigArrIndex++;
    }

    //1 more computation done even if the loop is not executed
    compCount++;

    //copy the rest of the stuff if left
    while(rightArrIndex < szRight){
        moveCount++;
        compCount++;
        newArr[bigArrIndex] = right[rightArrIndex];
        rightArrIndex++;
        bigArrIndex++;
    }
    //1 more computation done even if the loop is not executed
    compCount++;

    //copy the rest of the stuff if left
    while(leftArrIndex < szLeft){
        moveCount++;
        compCount++;
        newArr[bigArrIndex] = left[leftArrIndex];
        leftArrIndex++;
        bigArrIndex++;
    }

    //1 more computation done even if the loop is not executed
    compCount++;

    return newArr;
}


void mergeSort( int * arr, int size, int &compCount, int &moveCount){
    //to take the branch or not needs 1 comparison
    compCount++;

    if(size > 1){
        int mid = size/2;
        int * left = new int[mid];
        int * right = new int[size-mid];


        for(int i = 0; i < mid; i++){
            compCount++;
            left[i] = arr[i];
            moveCount++;
        }
        //1 more computation done even if the loop is not executed
        compCount++;

        for(int i = mid; i < size; i++){
            right[i-mid] = arr[i];
            moveCount++;
            compCount++;
        }
        //1 more computation done even if the loop is not executed
        compCount++;

        mergeSort(left,mid,compCount,moveCount);
        mergeSort(right,size-mid,compCount,moveCount);
        int * sortedArr = merge(left,mid,right,size-mid,compCount,moveCount);
        cout << "Done: ";
        for (int i = 0; i < size; ++i)
            cout << sortedArr[i] << " ";
        cout << endl;

        //delete[] left;
        //delete[] right;

        for(int i = 0; i < size; i++){
            arr[i] = sortedArr[size];
            moveCount++;
            compCount++;
        } 
        //1 more computation done even if the loop is not executed
        compCount++;
    }
}

【问题讨论】:

  • 请帮我调试一下。 -- 使用编译器自带的调试器。
  • @PaulMcKenzie 我不知道如何使用 gdb。我正在使用 g++ 编译器
  • 好了,现在是学习使用调试器的好时机。编程不仅仅是写代码、运行代码,如果有问题,去SO寻求帮助。学习如何调试代码是学习如何编写程序的一部分。
  • @PaulMcKenzie 我没有多少时间了,我正在尝试调试它。哈哈。我没有懈怠。但头脑越多越好。

标签: c++ sorting merge mergesort


【解决方案1】:

只有一行。评论中注明的修复:

        //delete[] left;
        //delete[] right;

        for(int i = 0; i < size; i++){
            arr[i] = sortedArr[i];    // fix from [size] to [i]
            moveCount++;
            compCount++;
        } 

注释:在mergeSort中,代码可以使用arr代替left,而不是分配left和right,用arr+mid代替right。少了两个分配。入口/辅助函数可以一次性分配与原始数组大小相同的临时数组,并将其作为参数传递给mergeSort(),然后将其作为参数传递给merge()。在这种情况下,mergeSort 所做的只是在堆栈上创建索引对,然后 merge 进行实际的合并和复制。

虽然可能超出了这个类的范围,但是也可以用两个相互递归的mergeSort版本来消除复制回来,一个是合并的数据以原始数组结尾,调用这个mergeSortO(),一个是合并的数据在临时数组中结束,调用这个 mergeSortT()。 mergeSortO() 调用 mergeSortT() 两次(左右两半),然后调用 merge() 从临时数组合并到原始数组。 mergeSortT() 调用 mergeSortO() 两次(左右两半),然后调用 merge() 将原始数组合并到临时数组,或者如果 size 为 1,则将原始数组中的一个元素复制到临时数组。

也可能超出类,另一种选择是自下而上的归并排序,因为大多数库,如 STL std::stable_sort() 使用自下而上归并排序的一些变体。

【讨论】:

  • 我照你说的做了,但还是一样。实际上,通过这样的数组来提高性能是一个绝妙的主意。但是没有表现:(
  • @ErinAvllazagaj - 你确定你做了改变(sortedArr[i])并重新编译了吗?我用你的例子尝试了这个,array[] = {34, 21, 8} 和其他一些小数组,它可以工作。
  • 感谢您的支持,我会尝试您的建议并希望它能够正常工作
  • @ErinAvllazagaj - 复制上面发布的代码,修复一行(sortArr[i]),然后再试一次。它应该工作。一旦它开始工作,在尝试进行任何改进之前备份源文件。
  • 非常感谢,我不敢相信我写了这么愚蠢的东西。谢谢你指出这一点。我一定是真的累了。那一行是问题
猜你喜欢
  • 2016-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-18
  • 2016-10-01
  • 1970-01-01
相关资源
最近更新 更多