就地随机选择算法

In place randomized selection algorithm

本文关键字:算法 选择 随机      更新时间:2023-10-16

我们目前正在研究算法,因此我将这个问题标记为"作业",尽管这不是一个与作业相关的任务。只是为了安全。

我们刚刚研究了随机选择算法,逻辑似乎很简单。从列表中选择一个元素,然后将该元素放在正确的位置。然后在一个子列表中重复该过程,直到索引处的元素就位。其中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都是我想要的元素的索引。

有没有第二个例子失败的地方?这是一个简单的一次失误吗?

谢谢大家!

这听起来很可疑:

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