难以将Merge排序为O(n log n)

时间:2014-10-02 05:02:00

标签: c++ arrays sorting mergesort

在完全披露中,我是一名学生,并且在合并排序方面遇到了麻烦。目的显然是有一个O(n log n),但它更多n ^ 2。我认为问题在于tempList,正如你在代码中看到的那样,但是在程序描述中它说使用static int tempList [LIST_SIZE]来避免降级。

这就是我所拥有的,运行时使用start大约是16000,这显然是合并排序的方法。

    void mergeSort(int randomNum[], int lowIdx, int highIdx)
    {
        int midIdx;

        if (lowIdx < highIdx)
        {
            midIdx = (highIdx + lowIdx) / 2;
            mergeSort(randomNum, lowIdx, midIdx);
            mergeSort(randomNum, midIdx + 1, highIdx);
            merge(randomNum, lowIdx, midIdx, highIdx);
        }
    } 

这是排序的第二部分

    void merge(int randomNum[], int lowIdx, int midIdx, int highIdx)
    {
        static int tempList[MAX_SORT];

        for (int count = 0; count <= highIdx; count++)
            tempList[count] = randomNum[count];

        int leftIdx = lowIdx,
        rightIdx = midIdx + 1,
        tempPos = lowIdx;

        while (leftIdx <= midIdx && (rightIdx <= highIdx))
        {
            if (tempList[leftIdx] <= tempList[rightIdx])
            {
                randomNum[tempPos] = tempList[leftIdx];
                leftIdx++;
            }
            else
            {
                randomNum[tempPos] = tempList[rightIdx];
                rightIdx++;
            }
        tempPos++;
        }

        while (leftIdx <= midIdx)
        {
            randomNum[tempPos] = tempList[leftIdx];
            tempPos++;
            leftIdx++;
        }

        while (rightIdx <= highIdx)
        {
            randomNum[tempPos] = tempList[rightIdx];
            tempPos++;
            rightIdx++;
        }
    }

程序的细节是我们有一个包含100000个随机数的数组,并使用各种排序算法对其进行排序。其他类型的工作正如预期的那样,但与大O应该是什么相比,这个似乎有很多。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:2)

不确定这是否是您的全部问题,但这是一个问题:

您正在randomNumtempList复制0highIdx,但您只能tempListlowIdx访问highIdx }}

这意味着您从0复制到lowIdx的所有项目都是浪费的副本。

解决方案:仅复制您需要的内容。

for (int count = lowIdx; count <= highIdx; count++)

答案 1 :(得分:0)

您可能需要考虑自下而上的合并排序。示例模板代码。 a []是要排序的数组,b []是一个与[]大小相同的临时数组。排序的数据可能以[]或b []结尾。这可以修改为始终以[]中的数据结束,方法是在开始时进行通过计数检查,如果存在偶数次通过,则可以选择跳过交换。

template <typename T>
T * BottomUpMergeSort(T a[], T b[], size_t n)
{
    for(size_t s = 1; s < n; s += 2)        // swap in place for 1st pass
        if(a[s] < a[s-1])
            std::swap(a[s], a[s-1]);
    for(size_t s = 2; s < n; s <<= 1){      // s = run size
        size_t ee = 0;                      // init end index
        while(ee < n){                      // merge pairs of runs
            size_t ll = ee;                 // ll = start of left  run
            size_t rr = ll+s;               // rr = start of right run
            if(rr >= n){                    // if only left run
                rr = n;
                BottomUpCopy(a, b, ll, rr); //   copy left run
                break;                      //   end of pass
            }
            ee = rr+s;                      // ee = end of right run
            if(ee > n)
                ee = n;
            BottomUpMerge(a, b, ll, rr, ee);
        }
        std::swap(a, b);                    // swap a and b
    }
    return a;                               // return sorted array
}

template <typename T>
void BottomUpCopy(T a[], T b[], size_t ll, size_t rr)
{
    while(ll < rr){                         // copy left run
        b[ll] = a[ll];
        ll++;
    }
}

template <typename T>
void BottomUpMerge(T a[], T b[], size_t ll, size_t rr, size_t ee)
{
    size_t o = ll;                          // b[]       index
    size_t l = ll;                          // a[] left  index
    size_t r = rr;                          // a[] right index

    while(1){                               // merge data
        if(a[l] <= a[r]){                   // if a[l] <= a[r]
            b[o++] = a[l++];                //   copy a[l]
            if(l < rr)                      //   if not end of left run
                continue;                   //     continue (back to while)
            while(r < ee){                  //   else copy rest of right run
                b[o++] = a[r++];
            }
            break;                          //     and return
        } else {                            // else a[l] > a[r]
            b[o++] = a[r++];                //   copy a[r]
            if(r < ee)                      //   if not end of right run
                continue;                   //     continue (back to while)
            while(l < rr){                  //   else copy rest of left run
                b[o++] = a[l++];
            }
            break;                          //     and return
        }
    }
}