编程珠玑课后习题

第一章 开篇

3.位图排序:在排序中,我们可以很容易的想到用数组来排序,一个元素标志一个数,但是,这样做太浪费空间了,我们可以以一个二进制位(bit)标志一个数,这样形成的排序就是位图排序。
位图排序源码如下,

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

#define N 10000000
#define M 1000000
#define BITSPERWORD 32
#define MASK 0x1F
#define SHIFT 5

int bits[1+(N-1)/BITSPERWORD];
int data[M];
void beset(int i)  { bits[i>>SHIFT] |= (1<<(i & MASK)); }
void bezero(int i) { bits[i>>SHIFT] &= ~(1<<(i & MASK));}
int  check(int i)  { return bits[i>>SHIFT] & (1<<(i & MASK));}

void main()
{
    int i,j;
    j=0;
    for(i=0; i<N;i++)
    {
        bezero(i);
    }

    for(i=0;i<M;i++)
    {
        data[i] = rand()%(N-1) + 1;
        beset(data[i]);
    }

    for(i=0;i<N;i++)
    {
        if(check(i))
        {
            printf("%d\t",i);
            j++;
            if(j % 10 == 0)
                            printf("\n");
        }
    }

    printf("Have %d number\n",j);

}

bezero()函数为置零,将每一位都设置为0,i>>SHIFT相当于i/32,表示i属于数组中的第几个元素;i & MASK相当于i%32,表示i属于该元素的第几个位。

beset()函数为置1。数据存在时,数据对应的位置为1。

check()函数为检查数据是否存在。遍历数组时,数据存在的位返回1,否则返回0.

4.生成(0~N)区间k个无序,不重复数字。

#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N = 10000000;
const int K = 10000000;
int randint( int l, int r ){
    return rand() % ( r-l ) + l;
}
int a[ N ];
int main(void){
    for( int i = 0; i < N; i++ )
        a[i] = i;
    for( int i = 0; i < K; i++ ){
        swap( a[i], a[ randint(i,N) ] );
        printf("%d\n",a[i]);
    }
    return 0;
}

将原来有序的数组打乱即可。。。
对于问题3的位图排序的随机数生成,有可能有重复数字产生,可以修改一下:

for(i=0;i<M;i++)
    {
        data[i] = rand()%(N-1) + 1;
        if(check(data[i]) == 0)     
            beset(data[i]); 
        else 
            i--;
    }

这样就可以避免重复了- -
运行时间如下
real 0m1.632s
user 0m0.288s
sys 0m0.516s

http://www.cnblogs.com/wuyuegb2312/p/3136831.html
http://www.cnblogs.com/Trony/archive/2012/09/01/2667064.html
http://www.fookwood.com/archives/605
未完

猜你喜欢

转载自blog.csdn.net/linda_ds/article/details/75933341