程序珠玑中第一章问题中,给出的实现是基于int型数组的,我自己改改采用char字符数组实现。
简单说明一下,因为采用的是char类型,那么一个字符占据的位数就是BITSPERCHAR=sizeof(char)*8了,那么如果有N位数字需要排序,那么需要的数组大小就是N/BITSPERCHAR+1。字符数组中,每一个字符都有BITSPERCHAR位,所以一个整数N,计算他在数组的下标就是N/BITSPERCHAR了,利用移位运算的特性,其实在这里就是N>>3。接着算出具体是在哪一位应该是N mod BITSPERCHAR 了,即N%8,利用位运算的特性,模8其实就是N与二进制数0000 0111(0x7)求与,然后将1移到指定的位置,1<<N%8。set的话就是求或了,cls就是对刚刚得到的数取反后求并,test就是取并看结果是否为1。
最后用到一个generateRand函数,我把他的实现也贴出来了,这个函数可以保证生成的数字是不重复的。
#include <stdio.h>
//每一个字符的位数
#define BITSPERCHAR sizeof(char)*8
//移位
#define SHIFT 3
//需要排序的数量
#define N 1000
//掩码
#define MASK 0x7
//根据N求出字符数组的大小,一位代表一个数字
char a[1+ N/BITSPERCHAR];
//set函数用于设置第i位
void set(int i){
a[i>>SHIFT] |= ( 1 << ( i & MASK ));
}
//cls函数用于清除第i位
void cls(int i){
a[i>>SHIFT] &= ~( 1 << ( i & MASK ));
}
//test函数用于检验第i位
int test(int i){
return a[i>>SHIFT] & (1<<(i&MASK));
}
int main(){
int* temp = generateRand(1000);
int num = 1+N/BITSPERCHAR;
for(int i=0; i<num;i++)
a[i]=0;
for(i=0;i<N;i++){
printf("%d ",temp[i]);
set(temp[i]);
}
printf("\n");
for(i=0;i<N;i++){
if(test(i))
printf("%d ",i);
}
return 0;
}
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void swap(int* array, int a ,int b){
int temp;
temp=array[a];
array[a]=array[b];
array[b]=temp;
}
int* generateRand(int n){
int* array = (int*)malloc(n*sizeof(int));
int i,a,b;
for(i=0;i<n;i++)
array[i]=i;
srand((unsigned)time(NULL));
for(i=0;i<n;i++){
a=(rand()*RAND_MAX+rand())%n;
b=(rand()*RAND_MAX+rand())%n;
swap(array,a,b);
}
return array;
}