到位随机选择算法

时间:2012-03-28 22:23:48

标签: c++ algorithm random selection

我们目前正在研究算法因此我将此问题标记为“家庭作业”,即使这不是与家庭作业相关的任务。为了安全起见。

我们刚研究了随机选择算法,逻辑似乎很简单。从列表中选择一个元素,然后将该元素放在正确的位置。然后在一个子列表中重复该过程,直到索引处的元素到位。其中index是您在排序列表中所需元素的位置。

这应该是快速排序算法的修改版本。但我们只对一个子列表进行排序,而不是两个子列表。因此性能提升(大哦)。

我可以使用外部存储(C ++和基于零的数组)成功实现此算法:

int r_select2(vector<int>& list, int i)
{
   int p = list[0];

   vector<int> left, right;

   for (int k = 1; k < list.size(); ++k)
   {
      if (list[k] < p)  left.push_back(list[k]);
      else     right.push_back(list[k]);
   }

   int j = left.size();

   if (j > i) p = r_select2(left, i);
   else if (j < i) p = r_select2(right, i - j - 1);

   return p;
}

但是,我想使用原位(就地)实现算法,而不是使用额外的子数组。我认为这应该是一项简单/琐碎的任务。但在某个地方,我的原位版本出错了。也许现在已经很晚了,我需要睡觉,但我看不出以下版本失败的根本原因:

int r_select(vector<int>& list, int begin, int end, int i)
{
   i = i + begin;
   int p = list[begin];

   if (begin < end)
   {
      int j = begin;
      for (int k = begin + 1; k < end; ++k)
      {
         if (list[k] < p)
         {
            ++j;
            swap(list[j], list[k]);
         }
      }

      swap(list[begin], list[j]);

      if (j > i) p = r_select(list, begin, j, i);
      else if (j < i) p = r_select(list, j + 1, end, i - j);
   }

   return p;
}

在这两个示例中,第一个元素被用作枢轴以保持设计简单。在这两个示例中,i是我想要的元素的索引。

第二个例子失败的任何想法?这是一个简单的逐个错误吗?

谢谢大家!

1 个答案:

答案 0 :(得分:2)

这听起来很可疑:

i = i + begin;
...
r_select(list, begin, j, i);