按排序顺序生成随机数

时间:2014-10-20 13:56:32

标签: c algorithm

我想按排序顺序生成随机数。 我在下面写了代码:

void CreateSortedNode(pNode head)
{
    int size = 10, last = 0;
    pNode temp;
    while(size-- > 0) {
        temp = (pnode)malloc(sizeof(struct node));
        last += (rand()%10);
        temp->data = last;//randomly generate number in sorted order
        list_add(temp);
    }
}

[编辑:] 期望数量将按增加或减少的顺序产生:即{2,5,9,23,45,68}

int main()
{
int size = 10, last = 0;
        while(size-- > 0) {
            last += (rand()%10);
            printf("%4d",last);
        }
return 0;
}

有更好的主意吗?

3 个答案:

答案 0 :(得分:1)

如果没有关于样本量或样本范围的任何信息,要知道以下内容是否有趣但不相关或解决方案并不容易,但是因为它在任何情况下都很有趣,所以这里就是。

问题:

O(1)空格中,从大小为n S的有序集合N生成大小为<S1,S2,…SN>的无偏序有序随机样本,以便样本中的元素与有序集中的元素的顺序相同。

解决方案:

  1. 概率n/|S|,请执行以下操作:

    • S1添加到示例中。

    • 递减n

  2. S1

  3. 中移除S
  4. 重复步骤1和2,每次使用S的新第一个元素(和大小),直到n为0,此时样本将具有所需数量的元素

  5. python中的解决方案:

    from random import randrange
    
    # select n random integers in order from range(N)
    def sample(n, N):
      # insist that 0 <= n <= N
      for i in range(N):
        if randrange(N - i) < n:
          yield i
          n -= 1
          if n <= 0:
            break
    

    解决方案的问题:

    需要O(N)次。我们真的想花费O(n)时间,因为n可能比N小得多。另一方面,我们希望保留O(1)空格,以防n也非常大。

    更好的解决方案(仅限大纲)

    (以下内容改编自Jeffrey Scott Visser的1987年论文,“一种有效的顺序随机抽样算法”,由于Visser博士的慷慨,可以从ACM数字图书馆免费获得。见{{3}请阅读论文了解详情。)

    如果我们可以根据某些分布生成一个随机数,而不是递增i并选择一个随机数,就像上面的python代码一样,那将是很酷的{{1将增加而不会产生任何元素。我们所需要的只是分布(显然取决于in的当前值。)

    当然,我们可以从对算法的检查中精确地推导出分布。但这并没有多大帮助,因为生成的公式需要大量时间来准确计算,最终结果仍为N

    但是,我们并不总是要准确计算它。假设我们有一些易于计算的合理良好的近似值,这些近似值一直低估概率(结果是它有时不会做出预测)。如果这种近似有效,我们就可以使用它;如果没有,我们将需要回退到准确的计算。如果这种情况很少发生,我们平均可能会达到O(N)。事实上,Visser博士的论文展示了如何做到这一点。 (附代码。)

答案 1 :(得分:0)

假设您只想生成三个随机数xyz,以便它们按排序顺序x <= y <= z生成。您将把它们放在一些C ++容器中,我将其称为D = [x, y, z]之类的列表,因此我们也可以说xD的组件0,或{{1等等。

对于首先为D_0绘制随机值的任何顺序算法,假设它出现2.5,然后这会告诉我们一些关于x必须是什么的信息,即{{1 }}

因此,以y的值为条件,您所需的随机数算法必须满足y >= 2.5的属性。如果您正在绘制的分布类似于统一分布,例如统一分布或高斯分布,那么很明显通常x将是涉及该分布密度的其他表达式。 (事实上​​,只有像“无限”的狄拉克三角洲这样的病态分布可能是独立的,对你的应用来说是无稽之谈。)

因此,我们可以充满信心地推测,p(y >= x | x) = 1 {em}的各种值的p(y >= x)不等于 p(y >= t | x)。这是依赖随机变量的定义。所以现在您知道随机变量t(最终列表中的第二个)在统计上与p(y >= t)无关。

另一种说明方式是,在您的输出数据y中,x的组件不是统计独立的观察结果。事实上,他们必须正相关,因为如果我们知道D比我们想象的更大,我们也会自动知道D大于或等于我们的想法。

从这个意义上讲,提供这种输出的顺序算法就是马尔可夫链的一个例子。序列中给定数字的概率分布有条件地取决于先前的数字。

如果你真的想要像这样的马尔可夫链(我怀疑你没有),那么你可以随意绘制第一个数字(对于x),然后绘制正增量,你将添加每个连续的数字,如下:

  1. y绘制一个值,例如2.5
  2. x绘制严格正值,例如13.7,因此x为2.5 + 13.7 = 16.2
  3. y-x绘制严格正值,例如0.001,因此y为16.201
  4. 等......
  5. 您只需要承认结果的组件在统计上不是独立的,因此您不能在依赖于统计独立性假设的应用程序中使用它们。

答案 2 :(得分:0)

早在 1979 年就解决了(由 Carnegie-Mellon 的 Bentley 和 Saxe 解决):

https://apps.dtic.mil/dtic/tr/fulltext/u2/a066739.pdf

解决方案在代码方面也非常紧凑!

他们的论文是用 Pascal 写的,我把它转换成 Python,所以它应该适用于任何语言:

from random import random

cur_max=100                       #desired maximum random number
n=100                             #size of the array to fill
x=[0]*(n)                         #generate an array x of size n

for i in range(n,0,-1):
  cur_max=cur_max*random()**(1/i) #the magic formula
  x[i-1]=cur_max                  

print(x)                          #the results

享受你排序的随机数...