数据结构与算法 试题2.7 - 生成前N个自然数的一个随机置换

数据结构与算法 2.7

习题2.7

假设需要生成前N个自然数的一个随机置换。例如,{3,4,1,5,2}和{5,2,3,1,4}就是合法的置换,但{5,4,1,2,1}却不是,因为数1出现了两次而数3却没有。 这个程序常用语模拟一些算法。我们假设存在一个随机数生成器RandInt(i,j),它以相同的概率生成i和j之间的一个整数。下面是三个算法:

  1. 如下填入从A[0]到A[N-1]的数组A;为了填入A[i],生成随机数直到它不同于生成的A[0],A[1]......A[i-1]时,在填入A[i]
  2. 同算法(1),但是要保存一个附加数组,称之为Used(用过的)数组。当一个随机数Ran最初被放入数组A的时候,置Used[Ran]=1。这就是说,当一个随机数填入A[i]时可以进一步测试是否该随机数已经被使用,而不是像第一个算法那样(可能)进行i步测试。
  3. 填写该数组使得A[i]=i+1。然后:
    for (i = 1; i < N; i++) {  
        Swap(&A[i], &A[RandInt(0, i)]);  
    } 
    
  • a. 证明这三个算法都生成合法的置换,并且所有的置换都是等可能的。
  • b. 对每一个算法给出你能够得到的尽可能准确的期望的运行时间分析。
  • c. 分别写出程序来执行每个算法10次,得出一个好的平均值。对于N=250, 500, 1000, 2000运行程序1;对于N=2500,5000,10000,20000,40000,80000运行程序2;对N=10000,20000,40000,80000,160000,320000,640000运行程序3。
  • d. 将实际的运行时间与你的分析时间进行比较
  • e. 每个算法的最坏情形的运行时间是什么?

参考资料

  1. 返回数组
  2. 数组作为参数
  3. 随机数
  4. PHP随机数函数-头文件
  5. PHP随机数函数-源文件

头文件

// 随机置换方法一
extern void RandRangOne(int[], int);
// 随机置换方法二
extern void RandRangTwo(int[], int);

源文件

#include <stdio.h>
#include <stdlib.h>

#include <time.h>

/**
 * 产生[min, max]之间的一个随机数
 * 注:参考PHP随机数生成的处理
 * @param min
 * @param max
 * @return 
 */
int RandInt(int min, int max) {
    srand((unsigned int)(time(0) * getpid()) ^ (unsigned int)(1000000.0));
    return min + (int)((double)((double)(max) - (min) + 1.0) * ((rand()) / ((RAND_MAX) + 1.0)));
}

/**
 * 随机置换算法一
 * @param a
 * @param size
 */
void RandRangOne(int a[], int size) {
    int i;
    for (i = 0; i < size; i++) {
        while (1) {
            int rand = RandInt(1, size);
            int flag = 0;

            int j;
            for (j = 0; j < i; j++) {
                if (a[j] == rand) {
                    flag = 1;
                    break;
                }
            }

            if (flag) {
                continue;
            }

            a[i] = rand;
            break;
        }
    }
}

/**
 * 随机置换算法二
 * @param a
 * @param size
 */
void RandRangTwo(int a[], int size) {
    int used[size], i;
    for (i = 0; i < size; i++) {
        while (1) {
            int rand = RandInt(1, size);

            if (used[rand] == 1) {
                continue;
            }

            a[i] = rand;
            used[rand] = 1;
            break;
        }
    }
}

调用示例

#include <stdio.h>
#include <stdlib.h>

#include "ext/s8/fun.h"

int main(int argc, char** argv) {
    int a[10];
    RandRangTwo(a, 10);

    int i;
    for(i = 0; i < 10; i++) {
        printf("%d\n", a[i]);
    }
    return (EXIT_SUCCESS);
}

转载于:https://my.oschina.net/stream/blog/688132

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值