我一直在失去价值并获得0。我的逻辑有什么不对?

时间:2016-02-21 21:55:58

标签: c++ sorting merge mergesort

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

我的分区是正确的,但是它合并了一个在它有0之前合并的数组。例如:如果我有[34] [21]我得到[21,34]但是当它与let' s说[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++;
    }
}

1 个答案:

答案 0 :(得分:0)

只需一行。注释中注明了修复:

        //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,而arr + mid而不是right。减少两次分配。一个入口/辅助函数可以一次分配与原始数组大小相同的临时数组,并将其作为参数传递给mergeSort(),而mergeSort()又将它作为参数传递给merge()。在这种情况下,所有mergeSort都会在堆栈上创建索引对,并且merge会执行实际的合并并复制回来。

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

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