【问题标题】:Having trouble getting Merge sort to be O(n log n)无法让合并排序为 O(n log n)
【发布时间】:2014-10-02 05:02:00
【问题描述】:

完全公开,我是一名学生,在合并排序方面遇到了麻烦。目的显然是有一个 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 个随机数的数组,并使用各种排序算法对其进行排序。其他种类按预期工作,但与 big-O 应该有的相比,这个似乎相差很多。

有人可以帮忙吗?

【问题讨论】:

    标签: c++ arrays sorting mergesort


    【解决方案1】:

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

    您将randomNum 复制到tempList,从0 复制到highIdx,但您只能从lowIdxhighIdx 访问tempList

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

    解决方案:只复制你需要的。

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

    【讨论】:

    • 非常感谢。我知道我的代码是正确的,除了涉及 tempList 的东西,但不确定哪里出了问题。这完全解决了它。
    【解决方案2】:

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

    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
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-19
      • 2011-12-12
      • 1970-01-01
      • 1970-01-01
      • 2011-12-11
      相关资源
      最近更新 更多