Iterative Merge Sort,与Bubblesort的速度相同

时间:2015-02-27 09:28:12

标签: c++ sorting iteration mergesort

我尝试使用嵌套循环实现迭代Merge排序。虽然这个算法排序正确(如排序后的事情顺序正确),但我知道这个实现有问题,因为我试图用它来排序更大的集合并将时间与较慢的排序进行比较,我最终得到了缓慢的时间对于这个迭代实现。例如,排序500个项目的时间为31毫秒,这个实现就像冒泡排序一样。

  int main()
  {

      int size;
      cin >>  size;
      //assume vector is already initialized with values & size
      vector<int> items(size);
      IterativeMergeSort(items, 0, size - 1);
  }
  void IterativeMergeSort(vector<int> &items, int start, int end)
  {
    vector<int> temp(items.size());
    int left, middle, right;
    for(int outer = 1; outer < 2; outer *= 2)
    {
    for(int inner = start; inner < end; inner = inner * outer + 1)
    {
        left = outer - 1;
        middle = inner;
        right = inner + 1;
        ItMerge(items, left, middle, right, temp);
    }
   }
 }
  void ItMerge(vector<int> &items, int start, int mid, int end, vector<int> &temp)
{
int first1 = start;
int last1 = mid;
int first2 = mid + 1;
int last2 = end;

int index = first1;
while(first1 <= last1 && first2 <= last2)
{
    if(items[first1] <= items[first2])
    {
        temp[index] = items[first1];
        first1++;
    }
    else
    {
        temp[index] = items[first2];
        first2++;
    }
    index++;
}
while(first1 <= last1)
{
    temp[index] = items[first1];
    first1++;
    index++;
}
while(first2 <= last2)
{
    temp[index] = items[first2];
    first2++;
    index++;
}
for(index = start; index <= end; index++)
{
    items[index] = temp[index];
}
}

3 个答案:

答案 0 :(得分:2)

您的算法不是合并排序。它试图成为,但它不是。

据我所知,应该发生的是内循环跨过子序列并合并它们,而外循环控制内循环的序列长度,从1开始,每次迭代加倍,直到那里只是两个子序列,他们合并。

但那不是你的算法正在做的事情。外循环的条件被破坏,因此外循环将只运行一次。并且内环并不成对地采用大致相等的子序列。相反,右子序列恰好是一个元素(midinnerrightinner+1),左子序列始终是目前使用的所有元素(leftouter-1outer是常数1)。因此,算法将重复合并已经排序的左子序列和单个元素右子序列。

这意味着实际上,您的算法是插入排序,除非您不插入到位,而是将排序的序列复制到缓冲区,在适当的时候插入新元素,然后复制结果背部。所以这是一种非常低效的插入排序。

答案 1 :(得分:0)

下面是自上而下和自下而上合并排序的一些优化示例的链接。自下而上合并排序有点快,因为它会跳过用于重复生成索引子对的递归序列,直到子对表示大小为1的运行。大部分时间用于合并,因此自下而上不是&#39那要快得多。自下而上合并传递的第一遍可以通过交换对而不是复制它们来优化。自下而上的合并排序以temp或原始数组中的排序数据结束。如果需要原始数组,则可以计算通过计数,如果计数为奇数,则第一次通过交换。

两个版本都可以在我的系统(Intel Core i7 2600k 3.4ghz)上在不到一秒的时间内对400万个64位无符号整数进行排序。

merge_sort using vectors works well with less than 9 inputs

对于向量或整数数组,计数/基数排序会更快。

答案 2 :(得分:0)

我终于明白了。

在伪代码中:

  for( outer = 1, outer < length, outer *=2)
     for(inner = 0; inner < length, inner = inner + (outer *2))
        left = inner
        middle = (inner + outer) - 1
        right = (inner + (outer * 2)) - 1
        merge(items, left, middle, right, temp)

在重新思考迭代合并排序应如何工作并查看几个实现之后,在合并方法中,我需要的只是检查传入的中间和右侧索引是否大于或等于向量大小(这样我们处理任何可能超出范围的值,然后像往常一样合并。另外,看this有助于理解它; also this。为了确保它与递归Merge Sort一样有效,我在两者上做了计时,并且两个(递归和迭代)实现产生500,1000,5000和10K值的相同时间进行排序(在某些情况下是迭代解决方案)产生了更快的时间)。