我们目前正在研究算法,因此我将这个问题标记为“家庭作业”,尽管这不是与家庭作业相关的任务。只是为了安全。
我们刚刚研究了随机选择算法,逻辑似乎很简单。从列表中选择一个元素,然后将该元素放在正确的位置。然后在一个子列表中重复该过程,直到索引处的元素就位。其中索引是您想要的元素在排序列表中的位置。
这应该是快速排序算法的修改版。但是我们只对一个子列表进行排序,而不是对两个子列表进行排序。因此性能提升(大哦)。
我可以使用外部存储(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;
}
但是,我想使用原位(in-place)实现算法,而不是使用额外的子数组。我相信这应该是一项简单/微不足道的任务。但是在某个地方,我的原位版本出错了。可能是时间太晚了,我需要 sleep 了,但是我看不到以下版本失败的根本原因:
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);
关于c++ - 就地随机选择算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9916535/