2015-10-19 137 views
0

有没有更好的方法来生成8位唯一随机号码在恒定时间?生成8位唯一随机数

以下实现返回8位唯一随机数,但复杂度为O(n = 256),因为它必须遍历is_generated []数组,直到它生成一个先前未生成的数组。另外它需要额外的空间is_generated

uint8_t 
random_octate(void) 
{ 
    static bool  is_generated[256] = {false}; 
    uint32_t  num = rand()%256; 

    while(is_generated[num]) 
    { 
     num = rand() % 256; 
    } 

    is_generated[num] = true; 
    return num; 
} 
+1

预洗牌值[0..255]用Fisher检验Yates是一个很好的答案,因为已经给出。我会补充说你的问题被打破了。保证不重复的256个数字不是随机的。它们是[0..255]的随机排列,这正是Fates-Yates所产生的。 – Gene

回答

6

生成(0..255),然后洗牌。然后逐个发布元素。混洗是O(n),为256个值完成一次,因此每个元素的成本为O(1);显然返回单个元素也是O(1)。

+0

因为n不能大于256,所以O(n)*是* O(1)。除了这个技术性之外,你可以使用F-Y递增地进行洗牌,所以你只需要做一次交换来产生下一个随机元素。当然,你必须将库初始化为{0..255},但这可以通过静态初始化来完成(这是另一个技术性) – rici

3

由于数据集是这样的限制不应该有在分配256个值的问题,他们洗牌并且为了提取它们,something like

#include <stdio.h> 
#include <stdint.h> 
static uint8_t data[256]; 
static int index; 

void init_random() 
{ 
    srand(NULL); 

    index = 0; 
    for (int i = 0; i < 256; ++i) 
    data[i] = i; 

    // bad choice, use fisher-yates for example 
    for (int i = 0; i < 10000; ++i) 
    { 
    int i1 = rand()%256, i2 = rand()%256; 
    uint8_t t = data[i1]; 
    data[i1] = data[i2]; 
    data[i2] = t; 
    } 
} 

uint8_t extract() 
{ 
    return data[index++]; 
} 


int main(void) 
{ 
    init_random(); 
    for (int i = 0; i < 100; ++i) 
    printf("%d\n", extract()); 
} 
+0

保持循环大小10000而不是256的好处最终是洗牌元素在数组数据? – Steephen

+1

首先,我指出这是一个不好的选择,应该使用适当的算法(如Fisher-Yates)。将想法提供给OP只是一个简单的实现,洗牌数量大于数据集大小,以至于有更多的概率将每个元素洗牌至少一次。 – Jack