Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我还能在哪里改进这种合并排序 虚拟索引和排序(索引和数据) { //基本情况 向量temp1,temp2,temp3; //对于(int i=0;i_C++_Mergesort - Fatal编程技术网

C++ 我还能在哪里改进这种合并排序 虚拟索引和排序(索引和数据) { //基本情况 向量temp1,temp2,temp3; //对于(int i=0;i

C++ 我还能在哪里改进这种合并排序 虚拟索引和排序(索引和数据) { //基本情况 向量temp1,temp2,temp3; //对于(int i=0;i,c++,mergesort,C++,Mergesort,您的代码过于复杂。合并排序有两个部分:divide和merge。每个部分都应该是一个函数 您还应该具有顶级功能(用户将使用的公共界面) 为了获得最大的速度,您应该在顶级函数中分配一次所需的所有额外内存,并将其向下传递以供较低级别的函数使用。(使用向量并根据数据长度调整大小。) 当(end-begin==0)是一对浪费的函数调用时,不要见底。当它们的差异为2时停止。对这两个函数进行排序,然后开始在树的后面工作 您的合并算法应该都在一个函数中,您可以对其进行一些清理。基本合并算法是: A和B都有元

您的代码过于复杂。合并排序有两个部分:divide和merge。每个部分都应该是一个函数

您还应该具有顶级功能(用户将使用的公共界面)

为了获得最大的速度,您应该在顶级函数中分配一次所需的所有额外内存,并将其向下传递以供较低级别的函数使用。(使用向量并根据数据长度调整大小。)

当(end-begin==0)是一对浪费的函数调用时,不要见底。当它们的差异为2时停止。对这两个函数进行排序,然后开始在树的后面工作

您的合并算法应该都在一个函数中,您可以对其进行一些清理。基本合并算法是:

  • A和B都有元素:
    • 如果A的第一个元素小于B的第一个元素:
      • 删除并将其附加到结果
      • 否则删除B并将其附加到结果中
  • 在结果中附加仍然包含元素(A或B)的序列

希望这能有所帮助。

首先,要知道霍尔将他的新排序命名为“快速排序”是有充分理由的——它比当时已知的其他排序(包括合并排序)要快得多。换句话说,不要指望合并排序能跟上快速排序(作为一般规则),几乎不管它的实现有多好

也就是说,您通常可以比这里更好地实现合并排序。特别是,合并排序可以“自下而上”而不是“自上而下”实现。现在,您的函数基本上将数组拆分为两半,然后调用自身对数组的每一半进行排序

所以,你做了很多递归调用,基本上每个都是计算需要排序的数组中间部分的索引。这给一个相对简单的计算增加了相当多的开销

最后,不管怎样,这样做的结果几乎是必然的。你总是不断地进行递归调用,直到一个分区只有一两个元素(大约)

就所需的额外空间而言,一个与输入大小相同的额外数组就足够了(尽管这不是绝对必要的,但就地合并技术增加了复杂性,因此它们更难正确写入,而且运行速度也更慢)

既然您知道要拆分数组,直到只得到两个项目,那么您可以首先从那里开始。只需获取第一对元素,如果它们的顺序不正确,则交换它们。对于数组的其余部分,继续使用对

然后进入合并阶段:将第一对与第二对合并,第三对与第四对合并,依此类推。继续对数组的其余部分进行合并。重复该过程,直到对整个数组进行排序


不过,您通常不希望一个分区中只有两个项目。您通常希望一次对(比如)10个项目进行插入排序,然后进入合并阶段(尽管精确的大小并不重要).

这里的问题最多是常数因素,而不是渐进性能。尽管如此,过早进行微观优化的风险很大。也就是说,在不那么过早的情况下,仍然值得学习如何进行优化,所以

首先,高性能排序总是混合算法如果n足够小,像插入排序这样的算法实际上是非常好的,所以当n变小时,实用的排序算法往往会切换策略。如果你对一百万个项目进行排序,而策略切换发生在n=10,听起来你可能只会受益于一个微不足道的10个项目排序,但这种情况大约会发生100000次对你的百万物品进行分类,这样累积的利益就能得到很好的回报

对于一个硬编码的which-permutation-am-I-in嵌套的ifs集合,甚至有一个非常小的n的情况,这样,对于每个置换,一个预先确定的移动/交换的最佳集合被应用。例如,对于n=3,有6种可能的项目顺序-6种情况需要检测,6种移动/交换需要计算。对于n=4,现在是24种情况,所以你会感到非常痛苦,不要忘记太多的代码也会减慢速度

一旦你确定算法本身是正确的,看看哪些工作可以从内部循环中移出。这有双重好处——首先,工作做得更少。其次,内部循环本身变得更简单,因此编译器可以更好地对其进行优化。当然,代价是代码的总体复杂性增加,而且要小心——编译器会uld已经在为您做一些这方面的工作了,因此很容易不仅浪费时间让编译器为其工作,而且会因为出错而引入错误,并阻止其他编译器优化,最终导致代码变慢

回归测试,测量前后的性能,如有疑问,检查生成的机器代码等

不过,一个明显的目标是——使用一个循环很方便,每次迭代时都要检查要合并的一个/另一个源是否耗尽,但这也是低效的。因此,当任一源耗尽时,检测一次,并使用一个特例循环来完成对另一个源的处理

另外,为了避免在每个循环中都进行穷举检查,如果其中项目最少的源数组有k个项目,则可以在不进行穷举检查的情况下安全地进行k次迭代。因此,可以在外部循环中检查k是什么,在k个项目上进行内部循环,而不进行穷举检查

第二点使内部循环在大多数合并过程中保持简单,最后的好处较少(因为每次检查时k都会变小)。它还增加了额外的复杂性-外部循环-因此它不是免费的
virtual Indexed<T>& sort(Indexed<T>& data)
{
    //base case

    Vector<T> temp1, temp2, temp3;
    //for (int i = 0; i < data.getSize(); i++)
    //{
    //  cout << data.getElementAt(i) << ", ";
    //}
    mergeSortHelper(data, 0, data.getSize() - 1, temp1, temp2);
    for (int i = 0; i < data.getSize(); i++)
    {
        cout << data.getElementAt(i) << ", ";
    }
    cout << endl;
    return data;
}

void mergeSortHelper(Indexed<T>& data, int begin, int end, Vector<T> &left, Vector<T> &right)
{
    //base case, if there is only 1 item in each side, merge them and return
    if ((begin - end) == 0)
    {
        //left.setElementAt(data.getElementAt(begin), 0);
        //left = storage;
        return;

    }
    else
    {
        //Vector<T> right;
        int midPoint = (end + begin) / 2;
        mergeSortHelper(data, begin, midPoint, left, right);
        mergeSortHelper(data, midPoint + 1, end, left, right);
        //perform merging


        int i = 0, leftCounter = 0, leftLimit = (midPoint - begin) + 1, rightCounter = 0, rightLimit = (end - (midPoint + 1)) + 1;
        for (int i = 0; i < leftLimit; i++)
        {
            if (i < leftLimit)
                left.setElementAt(data.getElementAt(begin + i), i);
            if (i < rightLimit)
                right.setElementAt(data.getElementAt(midPoint + 1 + i), i);
            //cout << left.getElementAt(i) << ", ";
        }
        while (leftCounter < leftLimit || rightCounter < rightLimit)
        {
            if (leftCounter >= leftLimit)
            {
                //done sorting the left side
                data.setElementAt(right.getElementAt(rightCounter), begin + i);
                //temp.setElementAt(right.getElementAt(rightCounter), i);
                rightCounter++;
            }
            else if (rightCounter >= rightLimit)
            {
                //done sorting the right side
                data.setElementAt(left.getElementAt(leftCounter), begin + i);
                //temp.setElementAt(left.getElementAt(leftCounter), i);
                leftCounter++;
            }
            else
            {
                if (left.getElementAt(leftCounter) < right.getElementAt(rightCounter))
                {
                    data.setElementAt(left.getElementAt(leftCounter), begin + i);
                    //temp.setElementAt(left.getElementAt(leftCounter), i);
                    leftCounter++;
                }
                else if (left.getElementAt(leftCounter) > right.getElementAt(rightCounter))
                {
                    data.setElementAt(right.getElementAt(rightCounter), begin + i);
                    //temp.setElementAt(right.getElementAt(rightCounter), i);
                    rightCounter++;
                }
                else
                {
                    data.setElementAt(right.getElementAt(rightCounter), begin + i);
                    //temp.setElementAt(right.getElementAt(rightCounter), i);
                    i++;
                    data.setElementAt(left.getElementAt(leftCounter), begin + i);
                    //temp.setElementAt(left.getElementAt(leftCounter), i);
                    leftCounter++;
                    rightCounter++;

                }

            }
            i++;
        }

    }

    //return temp;
template <typename T>
void BottomUpMergeSort(T a[], T b[], size_t n);
template <typename T>
void BottomUpCopy(T a[], T b[], size_t ll, size_t rr);
template <typename T>
void BottomUpMerge(T a[], T b[], size_t ll, size_t rr, size_t ee);

template <typename T>
void MergeSort(T a[], size_t n)             // entry function
{
    if(n < 2)                               // if size < 2 return
        return;
    T *b = new T[n];
    BottomUpMergeSort(a, b, n);
    delete[] b;
}

size_t GetPassCount(size_t n)               // return # passes
{
    size_t i = 0;
    for(size_t s = 1; s < n; s <<= 1)
        i += 1;
    return(i);
}

template <typename T>
void BottomUpMergeSort(T a[], T b[], size_t n)
{
size_t s = 1;                               // run size 
    if(GetPassCount(n) & 1){                // if odd number of passes
        for(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]);
        s = 2;
    }
    while(s < n){                           // while not done
        size_t ee = 0;                      // reset 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
        s <<= 1;                            // double the run size
    }
}

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
        }
    }
}
template <typename T>
void TopDownSplitMergeAtoA(T a[], T b[], size_t ll, size_t ee);
template <typename T>
void TopDownSplitMergeAtoB(T a[], T b[], size_t ll, size_t ee);
template <typename T>
void TopDownMerge(T a[], T b[], size_t ll, size_t rr, size_t ee);

template <typename T>
void MergeSort(T a[], size_t n)             // entry function
{
    if(n < 2)                               // if size < 2 return
        return;
    T *b = new T[n];
    TopDownSplitMergeAtoA(a, b, 0, n);
    delete[] b;
}

template <typename T>
void TopDownSplitMergeAtoA(T a[], T b[], size_t ll, size_t ee)
{
    if((ee - ll) == 1)                  // if size == 1 return
        return;
    size_t rr = (ll + ee)>>1;           // midpoint, start of right half
    TopDownSplitMergeAtoB(a, b, ll, rr);
    TopDownSplitMergeAtoB(a, b, rr, ee);
    TopDownMerge(b, a, ll, rr, ee);     // merge b to a
}

template <typename T>
void TopDownSplitMergeAtoB(T a[], T b[], size_t ll, size_t ee)
{
    if((ee - ll) == 1){                 // if size == 1 copy a to b
        b[ll] = a[ll];
        return;
    }
    size_t rr = (ll + ee)>>1;           // midpoint, start of right half
    TopDownSplitMergeAtoA(a, b, ll, rr);
    TopDownSplitMergeAtoA(a, b, rr, ee);
    TopDownMerge(a, b, ll, rr, ee);     // merge a to b
}

template <typename T>
void TopDownMerge(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
        }
    }
}