位图

位图应用: 非负数排序、去重等

实现:(利用 unsigned 数组: 考虑下为什么(提示:count))

假定一个正整数 n, 其所在位置为: int 数组 A[] 中第 n / 32 个整数中的第 n % 32 个 bit 处。

n / 32 <==> n >> 5

n % 32 <==> n & ox1f (或 31)。(注意: mod (2, 4, 8, 16, 32, 64, 128, 256, 512, ...)  <==> & (1, 3, 7, 15, 31, 63, 127, 255, 511, ...))

举例实现:1. 字符串去重 && 排序

#include <stdio.h>
unsigned A[8]; // 256 bit
char s[] = "4f3 ghl1ta;3gs4-s-s1j_av2bjl;j''faj;g2a3i4";

void set (char c) {
	A[c >> 5] |= (1 << (c & 31)); 
}
unsigned check (char c) {
	return A[c >> 5] & (1 << (c & 31));
}

int main() 
{
	int i = -1, sz = 0;
	while(s[++i]) 
		if(!check(s[i])) { s[sz++] = s[i]; set(s[i]);}
	s[sz] = 0;
	puts(s);
	i = 0, sz = 0;
	for(i = 0; i < 256; ++i) 
		if (check(i)) s[sz++] = i;
	puts(s);
	return 0;
}

 

 2. 数组中每个数最多保留 8 个。并排序。

选取 4 个 bits 来统计一个数。 最后计数排序。

#include <stdio.h>
#define UNIT  ((v) >> 3 ) 
#define POS (((v) & 7) << 2)  // 4 * (v % 8), in UNIT v / 8. 

unsigned A[128]; // 128 * 8 bits  > 4 * 255 bits
char s[] = "777777777777777777777fffffffffffffffffffffffffffff11116666";

void add (char v) {
	A[UNIT] += (1 << POS); 
}
void reduce(char v) {
	A[UNIT] -= (1 << POS);
}
unsigned count (char v) {
	return (A[UNIT] & (15 << POS)) >> POS;
}
void clear(char v) {
	A[UNIT] &= ~(0xf << POS);
}

int main() 
{
	int i = -1, sz = 0;
	puts(s);
	while(s[++i]) 
		if (count(s[i]) < 8) { add(s[i]); s[sz++] = s[i]; } // 去掉超出的数
	s[sz] = 0;
	puts(s);
	sz = 0;
	for(i = 0; i < 256; ++i) {
		while (count(i) > 0) 
			{ s[sz++] = i; reduce(i); }  // 计数排序
	}
	puts(s);
	return 0;
}

 

原文地址:https://www.cnblogs.com/liyangguang1988/p/3980159.html