编程珠玑之第一章习题4: 生成不同的随机顺序的随机整数及存储与读取

来源:互联网 发布:舜宇光学 知乎 编辑:程序博客网 时间:2024/05/24 04:37

2013-09-15 10:56 初版
2014-12-31 11:06 修改了程序中存在的一些bug。

这里对“生成小于n且没有重复的k个整数的问题”做一记录,以后扩充!
如下:
1.C++版:

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
/***********************************************************/
 // 程序名称:nRandomNum.cpp
 // 程序目的:生成0至n-1之间k个不同的随机顺序的随机整数
 // 程序来源:编程珠玑源码(bitsortgen.c -- gen $1 distinct
 //           integers from U[0,$2))
 // 日期:2013-9-15 9:02:42       JohnnyHu 修改
 //            2014-12-31 10:13:06  JohnnyHu 修改
 // 作者:    Jon Bentley
/***********************************************************/

#include <iostream>
#include <cstdlib>      /* srand, rand */
#include <ctime>        /* time */
#include <algorithm>    /* std::swap*/
#include <stdexcept>    /*std::domain_error*/

using namespace std;
const int N = 80;
const int K = 70;

/************************************************************************/
// 函数名称:bigrand
// 函数目的:生成范围在[0, 0x3FFFFFFF]之间的随机整数
// 使用条件:RAND_MAX = 32767(0x7FFF)
/************************************************************************/

int bigrand()
{
    return RAND_MAX*rand() + rand() + rand();
}

/************************************************************************/
// 函数名称:randint
// 函数目的:生成范围在[a, b]之间的随机整数
// 使用条件:RAND_MAX = 32767(0x7FFF); b >= a;
/************************************************************************/

int randint(int a, int b)
{
    if (b < a){
       throw domain_error("Argument to randint is out of range!");
    }
    return a +  bigrand() % (b - a  + 1);
}

/************************************************************************/
// 函数名称:set_randarray
// 函数目的:生成0至arrSize之间num个不同的随机顺序的随机整数
// 参数说明:参数1——数组,参数2——数组大小,参数3——范围(<=arrSize)
/************************************************************************/

void set_randarray(int arr[], const int arrSize, const int num)
{
    if (arrSize < 1 || num < 0 || num > arrSize){
       throw domain_error("Argument to SetArrAand is out of range!");
    }

    srand((unsigned) time(NULL));

    forint i = 0; i < arrSize; i++ ){
        arr[i] = i;
    }

    forint i = 0; i < num; i++ ){
        swap( arr[i], arr[randint(i, arrSize-1)] );   // 交换数组中的两个元素
    }

    return;
}

int main()
{
    int a[N];
    set_randarray(a, N, K);
    forint i = 0; i < K; i++ ){
        cout << a[i] << "\t";
    }

    return 0;
}

2、C语言版

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
#include <stdio.h>
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */
#include <assert.h>     /* assert */

const int N = 100;
const int K = 100;


/************************************************************************/
// 函数名称:bigrand
// 函数目的:生成范围在[0, 0x3FFFFFFF]之间的随机整数
// 使用条件:RAND_MAX = 32767(0x7FFF)
/************************************************************************/

int bigrand()
{
    return RAND_MAX*rand() + rand() + rand();
}

/************************************************************************/
// 函数名称:randint
// 函数目的:生成范围在[a, b]之间的随机整数
// 使用条件:RAND_MAX = 32767(0x7FFF); b >= a;
/************************************************************************/

int randint(int a, int b)
{
    assert( a <= b);
    return a +  bigrand() % (b - a  + 1);
}

/************************************************************************/
// 函数名称:set_randarray
// 函数目的:生成0至arrSize之间num个不同的随机顺序的随机整数
// 参数说明:参数1——数组,参数2——数组大小,参数3——范围(<=arrSize)
/************************************************************************/

void set_randarray(int arr[], const int arrSize, const int num)
{
    assert(arrSize > 0 && num > 0 && arrSize >= num);

    srand((unsigned) time(NULL));

    forint i = 0; i < arrSize; i++ ){
        arr[i] = i;
    }

    int index, tmp;
    forint i = 0; i < num; i++ ){
        index = randint(i, arrSize-1);

        // 交换数组中的两个元素
        tmp = arr[i]; arr[i] = arr[index]; arr[index] = tmp;
    }

    return;
}


int main()
{
    int a[N];
    set_randarray(a, N, K);
    forint i = 0; i < K; i++ ){
        printf("%d\t", a[i]);
    }

    getchar();
    return 0;
}

输出结果:



3.以字符文本形式存储100w整数:

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
#include <stdio.h>
#include <stdlib.h>        /* srand, rand */
#include <time.h>      /* time, clock_t*/
#include <assert.h>     /* assert */
#include <string.h>        /* memset*/

#define error( str )         fatal_error( str )
#define fatal_error( str )   fprintf( stderr, "%s\n", str ), exit( 1 )


/************************************************************************/
// 函数名称:bigrand
// 函数目的:生成范围在[0, 0x3FFFFFFF]之间的随机整数
// 使用条件:RAND_MAX = 32767(0x7FFF)
/************************************************************************/

int bigrand()
{
    return RAND_MAX*rand() + rand() + rand();
}

/************************************************************************/
// 函数名称:randint
// 函数目的:生成范围在[a, b]之间的随机整数
// 使用条件:RAND_MAX = 32767(0x7FFF); b >= a;
/************************************************************************/

int randint(int a, int b)
{
    assert( a <= b);
    return a +  bigrand() % (b - a  + 1);
}

/************************************************************************/
// 函数名称:set_randarray
// 函数目的:生成0至arrSize之间num个不同的随机顺序的随机整数
// 参数说明:参数1——数组,参数2——数组大小,参数3——范围(<=arrSize)
/************************************************************************/

void set_randarray(int arr[], const int arrSize, const int num)
{
    assert(arrSize > 0 && num > 0 && arrSize >= num);

    srand((unsigned) time(NULL));

    forint i = 0; i < arrSize; i++ ){
        arr[i] = i;
    }

    int index, tmp;
    forint i = 0; i < num; i++ ){
        index = randint(i, arrSize-1);

        // 交换数组中的两个元素
        tmp = arr[i]; arr[i] = arr[index]; arr[index] = tmp;
    }

    return;
}

int main()
{
    const int N = 20;
    const int K = 20;

    int a[N];
    set_randarray(a, N, K);

    FILE* iofile = fopen("unsortfile.txt""w");
    if (NULL ==  iofile){ fatal_error("不能打开unsortfile.txt文件!\n"); }

    // 把数组中的k(个)数据写入到文件中
    forint i = 0; i < K; i++ ){ fprintf(iofile, "%d\t", a[i]); }
    fclose(iofile);

    memset(a, 0sizeof(a));           // 数组a清零

    clock_t start_time = clock();      // 开始时间

    FILE* iofile2 = fopen("unsortfile.txt""r");
    if (NULL ==  iofile2){ fatal_error("不能打开unsortfile.txt文件!\n"); }

    // 从文件中读取数据
    int index = 0;
    while(fscanf(iofile, "%d", &a[index]) != EOF){ index++; }
    fclose(iofile2);

    clock_t end_time = clock();        // 结束时间

    float cost_time = (float)(end_time - start_time) / CLOCKS_PER_SEC;
    printf("文件中的记录数:%d\n", index);
    printf("读文件耗时:%5.3f秒\n", cost_time);

    return 0;
}

输出结果如下:


4. 以二进制形式存储:

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
int main()
{
    const int N = 10000;
    const int K = 10000;

    int a[N];
    set_randarray(a, N, K);

    FILE* iofile = iofile = fopen("b_unsortfile.txt""wb");
    if (NULL ==  iofile){ fatal_error("不能打开b_unsortfile.txt文件!\n"); }

    // 把数组中的数据以二进制写入到文件中
    fwrite(a, sizeof(int), sizeof(a)/sizeof(int), iofile);
    fclose(iofile);

    memset(a, 0sizeof(a));           // 数组a清零

    clock_t start_time = clock();      // 开始时间

    FILE* iofile2 = fopen("b_unsortfile.txt""rb");
    if (NULL ==  iofile2){ fatal_error("不能打开b_unsortfile.txt文件!\n"); }

    // 从二进制文件中读取数据
    int index = 0;
    while(fread(&a[index], sizeof(int), 1, iofile2) != 0){
        if (!feof(iofile2)){ index++; }
    }
    fclose(iofile2);

    clock_t end_time = clock();        // 结束时间

    float cost_time = (float)(end_time - start_time) / CLOCKS_PER_SEC;
    printf("文件中的记录数:%d\n", index);
    printf("读文件耗时:%5.3f秒\n", cost_time);

    return 0;
 }

输出结果:


注:本以为以二进制形式存储的100w文本文件所占存储空间会小一点,没想到更大,达到38M多,相反字符串存储的文本却只有8M左右大小,从读文件来看,二进制的读文件耗时也较长,不知道我有没算错!!!