编程珠玑第一章习题

2、用位逻辑运算实现,使用位逻辑运算实现位向量所指实现位向量的设置,清零以及探测功能。

#define BITPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1+N/BITPERWORD]

//设置数组第i位为1
void set(int i)
{
        a[i>>SHIFT] |= (1<<(i&MASK));
}

//清空数组第i位为0
void clr(int i)
{
        a[i>>SHIFT] &= ~ (1<<(i&MASK));
}
//查询数组第i位数字
void test(int i)
{ 
     return a[i>>SHIFT] &(1<<(i&MASK));
}
算法解析:
1.set算法中i>>SHIFT相当于i/32,也就是2^5,功能是找出i对应数组中到哪一行,每一行都是32Bit,需要将相应到位置置为0或者1;需要1<<(i&MASK),其中i&MASK是计算需要左移的位数,然后把1向左移动这么多位,剩下的就是和数组中的元素或运算。
2、clr算法中通过1<<(i&MASK),其中i&MASK是计算需要左移的位数,然后把1向左移动这么多位,然后把该数字取反,和数组中到元素与运算,即可置第i位为0。

3、test算法中通过1<<(i&MASK),其中i&MASK是计算需要左移的位数,然后把1向左移动这么多位,然后把和数组中到元素与运算,数组中元素为1就返回1,数组中元素为0就返回0。


4、如何生成[0,n-1]之间的k个不同的随机顺序的随机整数(无重复)?

void random(int *arr, int k, int n)
{
	for(int i = 0; i < k; i++)
		swap(arr[i], arr[i + rand() % (n - i)]);
}



5、那个程序员说他又1MB的可用存储空间,但是我们概要描述的代码需要1.25MB的空间。他可用不费力气的索取到额外的空间。如果1MB空间是严格的边界,你会推荐如何处理呢?

1、找稀疏位,比如问题中的整数时电话号码;
2.使用两趟排序,在2n的时间开销和n/2的空间开销完成排序。



6、如果那个程序员说的不是每个整数最多出现一次,而是每个整数最多出现10次,你又如何建议他呢?你的解决方案如何随着可用存储空间总量的变化而变化呢?

/*
 * Copywrite @ jfk, 2012/10/17
 * Statement when Ref.
 */

#include <stdio.h>

/*
 * 每个整数最多出现10次,需要使用4bit表示,
 * 因此,一个int型数据可以表示8个整数。
 */
#define WORDS_PER_INT 8
#define SHIFT 3
#define MASK 0x07
#define CHECK_0 0x0F
#define N 10000000

int a[1 + N/WORDS_PER_INT];

/*
 * set()函数将整数i的计数加1。
 * 实现思路:
 * 1.确定offset。判断整数i所在a[]数组下标,用i除以8(即右移3位,i>>SHIFT)得到;
 * 2.确定value。取i除以8的余数"(i & MASK)",判断i位于当前a[]元素记录的哪一个数字,
 *   由于每一个数字包含4 bits,因此乘以4得到当前位置,即((i & MASK) * 4);
 * 3.将当前位置的数值增1。即,a[i]的值加上(1<<((i & MASK) * 4));   
 */
void set(int i) { a[i>>SHIFT] += (1<<((i & MASK) * 4));}

/*
 * clr()函数将整数i出现的次数减times次,默认减1次;
 * 思路:类比set()的实现思路,CHECK_0用于查看当前i的次数
 * 边界处理:当a[]中记录该整数的次数小于times次时,直接清0,防止影响到其他位
 */
void clr(int i, int times = 1)
{
	int tmp;
	tmp = a[i>>SHIFT] & (CHECK_0<<((i & MASK) * 4));
	tmp>>((i & MASK) * 4);
	if(tmp < times)
		 a[i>>SHIFT] -= (tmp<<((i & MASK) * 4));
	else
		 a[i>>SHIFT] -= (times<<((i & MASK) * 4));
}

/*
 * test()函数打印整数i的值和a[]中记录i出现的次数
 */
void test(int i)
{
	int tmp;
	tmp = a[i>>SHIFT] & (CHECK_0<<((i & MASK) * 4));
	tmp = tmp>>((i & MASK) * 4);

	if(tmp != 0)
		printf("Integer: %d, Times: %d\n", i, tmp);
}

void main()
{
	// User Define
}



   


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值