第一章 开篇
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
未完