问题描述:假设需要生成前N个自然数的一个随机置换。例如,{4,3,1,5,2} 和 {3,1,4,2,5} 就是合法的置换,但 {5,4,1,2,1} 却不是,因为数1出现了两次而数 3 缺没有。这个程序常常用于模拟一些算法。我们假设存在一个随机数生成器 randInt(i, j) ,它以相同的概率生成 i 和 j 之间的一个整数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include <stdio.h>
#include <stdlib.h>
void swap (int *a, int *b) {
int t;
t = *a;
*a = *b;
*b = t;
}
int RandInt(int i, int j) {
if (i == 0) {
return rand() % (j + 1);
} else {
return rand() % (j + 1 - i) + i;
}
}
// 1.如下填入 A[0] 到 A[N-1] 的数组 A;为了填入 A[i] ,生成随机数直到它不同于已经生成的 A[0], A[1], ... , A[i-1] 时,再将其填入 A[i] 。
void fun1(int a[], int n) {
int tmp;
int i = 0;
int j;
while (i < n) {
tmp = RandInt(0, n-1);
for ( j = 0; j < i; j++) {
if (tmp == a[j]) {
break;
}
}
if (j == i) {
a[i] = tmp;
i++;
}
}
}
// 2.同算法1,但是要保存一个附加的数组,称之为 Used(用过的)数组。
// 当一个随机数 Ran 最初被放入数组A的时候,置Used[Ran]=1。
// 这就是说,当用一个随机数填入 A[i] 时,可以用一步来测试是否该随机数已经被使用,而不是像第一个算法那样(可能)进行 i 步测试。
void fun2 (int a[], int n) {
int tmp;
int used[n];
for (int i = 0; i < n; i++) {
used[i] = 0;
}
int i = 0;
while (i < n) {
tmp = RandInt(0, n-1);
if (used[tmp] == 0) {
a[i] = tmp;
used[tmp] = 1;
i++;
}
}
}
// 3.填写该数组使得 A[i] = i + 1。然后
// for(i = 1; i < N; i++)
// swap(&A[i], &A[randInt(0, i)]);
void fun3 (int a[], int n) {
int i;
for (i = 0; i < n; i++) {
a[i] = i;
}
for (i = 0; i < n; i++) {
swap(&a[i], &a[RandInt(0, i)]);
for (int i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n \n");
}
}
int main() {
int a[5];
fun3(a, 5);
for (int i = 0; i < 5; i++) {
printf("%d \n", a[i]);
}
}
|