我制作的程序可以测试和比较多键顺序搜索和插值二进制搜索的统计信息。我正在征求意见:
对于随机生成的整数数组进行排序的最佳方法是什么,甚至在给定的上下文中将其生成为有序的(如果有意义的话)?
我正在研究一些排序技巧,但是,如果你记住重点是搜索(不排序)性能,所有的高级排序似乎在一种实用方法中使用相当复杂。考虑到阵列必须大于10 6 (用于测试目的),不能选择修改/冒泡,选择或插入排序。
附加限制是所有数组成员必须唯一。
现在,我最初的想法是将间隔 [INT_MIN,INT_MAX] 分成 n 间隔( n >作为数组长度,然后将 0 的随机整数添加到 2 32 / n (向下舍入),到每个区间开始。
问题是这个:
我认为,随着 n 越来越接近 2 32 ,就像我的那样,插值搜索开始提供更好更好的结果,因为它的插值变得更加准确。
然而
如果我完全依赖伪随机数生成器(如rand();
),它们的色散特性决定了生成然后排序的相同趋势数组,即 - 随着大小越来越接近int
限制,插值在确定最可能的位置时变得更好。当 n 上升到 INT_MAX 时,均匀性/频散特性会丢失,因此,由于规定的限制,插值似乎总能获胜。
在你认为合适的时候,请随意讨论,批评和澄清这个问题,但我非常渴望得到一个答案,因为测试似乎是插入式的,无论哪种方式,我想要公平地分析它们。简而言之:我希望确信我最初的想法并没有进一步倾斜插值的尺度,我想使用它因为它的 O( n)的
答案 0 :(得分:3)
这是一种生成有序随机序列的方法。这使用 Knuth的算法S ,取自 Programming Pearls 一书。
这需要一个在[0,1]范围内返回随机双精度的函数。我以my_rand()
为例。我还修改了它以获取目标的输出迭代器。
namespace
{
std::random_device rd;
std::mt19937 eng{ rd() };
std::uniform_real_distribution<> dist; // [0,1)
double my_rand() { return dist(eng); }
}
// Programming Pearls column 11.2
// Knuth's algorithm S (3.4.2)
// output M integers (in order) in range 1..N
template <typename OutIt>
void knuth_s(int M, int N, OutIt dest)
{
double select = M, remaining = N;
for (int i = 1; i <= N; ++i) {
if (my_rand() < select / remaining) {
*dest++ = i;
--select;
}
--remaining;
}
}
int main()
{
std::vector<int> data;
knuth_s(20, 200, back_inserter(data)); // 20 values in [1,200]
}
答案 1 :(得分:2)
所以你想生成一个具有N个唯一随机数的“数组”,它们必须按排序顺序排列?这听起来像是std::set
的完美用法。将元素插入set
时,它们会自动为我们排序,而一个集合只能包含唯一元素,因此它会检查是否已生成随机数。
std::set random_numbers;
std::random_device rd;
std::mt19937 mt(rd());
while (random_numbers.size() < number_of_random_numbers_needed)
{
random_numbers.insert(mt());
}
然后,如果您不想将其保留为集合,则可以将该集转换为其他内容,例如std::vector
或std::array
。
答案 2 :(得分:1)
如何从统计属性生成排序数组?
这可能需要一些挖掘,但您应该能够通过添加随机差异来生成整数,其均值是整个样本的标准差。
这在范围边界引发了一些问题,但考虑到样本的大小,你可能会忽略它。
答案 3 :(得分:0)
好的,我已决定将责任转移到内置的PRNG并执行以下操作:
将 n rand()
结果添加到二进制树并按顺序遍历数组(从最左边开始)叶)。