【问题标题】:Randomly generated sorted arrays: search performances comparison [closed]随机生成的排序数组:搜索性能比较 [关闭]
【发布时间】:2016-01-09 23:24:33
【问题描述】:

我正在制作一个程序来测试和比较多键顺序搜索和插值二分搜索的统计数据。我在征求意见:

在给定的上下文中,对随机生成的整数数组进行排序,甚至像排序后的数组一样生成它的最佳方法是什么(如果这有意义的话)

我正在研究一些排序技术,但是,如果您记住重点在于搜索(而不是排序)性能,那么所有高级排序似乎仅用于一种实用程序方法相当复杂。考虑到数组必须大于 106(用于测试目的),修改/冒泡、选择或插入排序不是一个选项。

额外的限制是所有的数组成员必须是唯一的

现在,我最初的想法是将区间 [INT_MIN,INT_MAX] 分成 n 个区间(n 是数组长度),然后将一个随机整数从 0232/n(向下舍入)添加到每个间隔开始.

问题是这样的

我认为,随着 n 越来越接近 232,就像我的一样,插值搜索开始提供越来越好的结果,因为它的插值变得更加准确。

但是:

如果我只依赖伪随机数生成器(如rand();),它们的分散特性决定了生成-然后-排序数组的相同趋势,也就是说 - 随着大小接近int 限制,插值在精确定位最可能的位置方面会变得更好。当 n 上升到 INT_MAX 时,均匀性/分散性特征会丢失,因此,由于规定的限制,插值法似乎总是获胜。

如果您认为合适,请随意讨论、批评和澄清这个问题,但我非常渴望得到答案,因为无论哪种方式,测试似乎都受到 Interpolation 的青睐,我想公平地分析它们。简而言之:我想确信我最初的想法不会进一步向有利于插值的方向倾斜,我想使用它,因为它是 O(n) .

【问题讨论】:

  • 我不确定我是否正确,您是否想要一种方法来生成排序整数的随机数组,条件是数组很大 (10^6)?对哪些项目应该有任何定义(传播、均匀性......)?
  • @Amit 只是它们是随机的、唯一的和排序的。
  • 所以 [1,2,3,6,7,8] 有效吗?
  • 所以走吧.. 对于每个元素,将值设置为 a[i-1]+random(x) 其中 random(x) i> 是一个正整数界限,因此它为 ni 个元素留出了足够的空间(应该很容易计算)。
  • 我投票决定关闭它,因为它主要是基于意见的(也太面包了),此类问题不适用于本网站。但是,如果“修改/冒泡、选择或插入”是您知道的唯一排序方法,那么您肯定需要更多阅读。

标签: c++ algorithm sorting random linear-interpolation


【解决方案1】:

这是一种生成有序随机序列的方法。这使用 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]
}

Demo in ideone.com

【讨论】:

  • 当 m 的大小与 n 大致相似时,这种技术可以合理地工作。但是,如果 m
【解决方案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::vectorstd::array 之类的其他内容。

【讨论】:

  • 当然,但我应该说这个程序的重点是从头开始制作所有内容(即基本类型)并评估算法的质量。
  • @StefanStanković 为什么要重新发明轮子?
  • 因为 60 岁的算法和数据结构教授这么说。我很幸运,我不必自己制作 PRGN。 :D
  • @StefanStanković 然后实现你自己的set。网上有很多关于如何制作的信息。
【解决方案3】:

从统计属性生成排序数组怎么样?

这可能需要一些挖掘,但您应该能够通过添加一个随机差来按顺序生成整数,该随机差的平均值是整个样本的标准偏差。

这会在范围边界产生一些问题,但考虑到样本的大小,您可能可以忽略它。

【讨论】:

    【解决方案4】:

    好的,我决定将责任转移到内置 PRNG 并执行以下操作:

    n rand() 结果添加到二叉 tree 并按顺序遍历数组(从最左边的叶子开始) .

    【讨论】:

    • 如果你的 rand() 多次给你相同的数字会发生什么?你最终会得到少于 n 个数字,对吧?
    • @Boris 不,元素数量仅在成功添加时增加,结束条件是添加了 n 个元素,而不是生成。
    猜你喜欢
    • 1970-01-01
    • 2014-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 2014-04-04
    • 1970-01-01
    相关资源
    最近更新 更多