Problem Description: Suppose you need to generate a random permutation of the first n natural numbers. For example, {4,1,2,5,2} and {3,1,4,2,5} are legal permutations, but {5,4,1,2,1} is not, because the number 1 appears twice and the number 3 is missing. This program is often used to simulate some algorithms. We assume that there is a random number generator Randint (i, j), which generates an integer between I and J at the same probability. Here are three algorithms:
1. Fill in an array of a[0] to a[n-1], fill in a[i], generate a random number until it differs from the a[0],a[1], ..., a[i-1], and then populate it with A[i].
2. Same as algorithm 1, but to save an additional array, called used (used) array. When a random number Ran was initially put into array A, the used[ran]=1 was placed. This means that when a random number is filled in with a[i], one step can be used to test whether the random number has been used, rather than the I test, as in the first algorithm (possibly).
3. Fill in the array to make the a[i]=i+1. And then:
for 1; i < N; i++ Swap (&a[i], &a[randint (0, i)]);
Write the program to execute each algorithm 10 times, to obtain a good average. For n=250,500,1 000,2 000 Run Program 1, to n=2500,5 000,10 000,20 000,40 000,80 000 Run program 2; to N=1 0000,2 0000,4 0000,8 0000,160 000,320 000, 640 000 Run program 3.
Realize:
1 //returns a random number in [I, J]2 intRandint (intIintj)3 {4 if(J-i = =0)5 returni;6 Else if(J-i <0)7 return 0;8 Else9 returnRand ()% (j-i) +i;Ten } One A //Algorithm 1 - intFillArray1 (intA[],intN) - { the intCount, ran, K; - -Count =0; - while(Count <N) + { -ran = Randint (0, n); + for(k =0; K < count; k++) A { at if(A[k] = =ran) - Break; - } - if(k = =count) - { -A[count] =ran; incount++; - } to } + return 1; - } the * //Algorithm 2 $ intFillArray2 (intA[],intN)Panax Notoginseng { - int*used, count, ran; the +Used = (int*)calloc(N,sizeof(int)); A if(used = =NULL) the return 0; + -Count =0; $ while(Count <N) $ { -ran = Randint (0, n); - if(Used[ran] = =0) the { -A[count] =ran;WuyiUsed[ran] =1; thecount++; - } Wu } - Free(used); About return 1; $ } - - Static voidSwapintBint*b) - { A inttemp = *A; +*a = *b; the*b =temp; - } $ the //Algorithm 3 the intFillArray3 (intA[],intN) the { the inti; - in for(i =0; I < n; i++) theA[i] = i +1; the for(i =0; I < n; i++) AboutSwap (&a[i], &a[randint (0, i)]); the}
The above algorithms have two main problems:
1). Dynamic array problem: limited available memory
In algorithm 2, it is required to do array subscript "used[ran]=1" with random numbers, which means that we must use a variable-length array used array with the largest number of random elements. vs2013 compiler does not support this feature, I chose the dynamic Memory allocation malloc () to implement the used array. This is limited by the amount of available memory.
2). C Random Number problem: limited range of random numbers
C generates pseudo-random numbers using Srand () and Rand (). We know that they can only produce a value between [0, Rand_max]. A maximum of (rand_max+1) non-repeating random numbers can be generated. When n > rand_max+1, the algorithm keeps trying to get new random numbers that are not duplicated and into a dead loop.
If you have a better algorithm, welcome to the communication.
Data structure and algorithm analysis (C language description) Exercise 2.7