《编程珠玑》(第二版)第一章习题2(用位运算实现位向量)

《编程珠玑》第一章提出了一个排序问题,可以用位图或位向量来表示。如可用一个20位长的字符串来表示一个所有元素都小于20的简单非负整数集合,如集合{1,2,3,5,8,13}可以表示为:

0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0

代表集合中数字的位都置为1,其他所有的位都置为0。

若给定表示文件中整数集合的位图数据结构,则可以分三个自然阶段来编写程序。第一阶段将所有的位都置为0,从而将结合初始化为空。第二阶段读入文件中的每个整数来建立结合,将每个对应的位都置为1。第三个阶段检验每一位,如果该位为1,就输出对应的整数。伪代码如下:

/*phase 1: initialize set to empty*/
for i=[0,n)
    bit[i]=0
/*phase 2: insert present elements into the set*/
for each i in the input file
     bit[i]=1
/*phase 3: write sorted output*/
for i=[0,n)
     if bit[i]==1
       write i on the output dile
一个字符占一个字节,也就是4个位,但是我们只需要一个位来表示,这样还是会造成浪费。可以用整数数组来模拟位数组。下面是习题2的参考答案,使用位逻辑运算来实现位向量图。

// bitmap.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include

#define BITSPERWORD 32 //表示一个整型含有32位
#define SHIFT 5
#define MASK 0x1F  //0000000000000000 0000000000011111
#define N 10000000  //表示1000万个整数

using namespace std;

int a[1 + N / BITSPERWORD];//使用整型数组模拟1000万个位的数组

void set(int i){
	//i>>SHIFT相当于i/32,表示该数由第几个整数表示,i&MASK相当于i%32,表示该数在整数中的第几个位
	//1<<(i&MASK)就将该位设为1
	a[i >> SHIFT] |= (1 << (i&MASK)); 
}
void clr(int i)
{
	a[i >> SHIFT] &= ~(1 << (i&MASK));
}
int test(int i)
{
	return a[i >> SHIFT] & (1 << (i&MASK));
}

int _tmain(int argc, _TCHAR* argv[])
{
	
	int i;
	for (i = 0; i < N; ++i)
		clr(i);
	cout << "输入数据:" << endl;
	while (cin >> i)
		set(i);
	cout << "输出结果:" << endl;
	for (i = 0; i < N; ++i)
	{
		if (test(i))
			cout << i <<" " ;
	}
	cout << endl;
	return 0;
}

实验结果如下:

《编程珠玑》(第二版)第一章习题2(用位运算实现位向量)_第1张图片


后记:

输入数据限制在相对较小的范围内,数据没有重复的情况下,可以考虑使用位图来存储数据实现排序。


参考:

http://blog.chinaunix.net/uid-26548237-id-3759520.html

你可能感兴趣的:(算法)