OJ-位图算法

题目描述:

位图法就是bitmap的缩写,是用每一个bit位来存放某种状态,适用于大规模数据的查找和排序。位图算法称的上是最简单的算法,只需要一个for循环就能够搞定排序和查找,但是同时它也是对待操作的数据要求最苛刻的,首先这些数据必须是正整数,且数据不能重复,其次要大致知道这些数据的范围,且有一定的聚集性。

数据结构为:unsigned int bitmap[N]  ,其可以表示的数据范围是0~N*32-1
常用的操作:
置位:bitmap[n / 32] |= (1UL << (n & 31));//表示第n位置1
复位:bitmap[n / 32] &= ~(1UL << (n & 31));//表示第n位置0
获取第i位:puiBitmap[i / 32] & (1UL << (i & 31))
本题实现的功能为搜索指定区间内第uiNum个被占的位(即该位为1),本文采用两种方法来实现,一种是采用顺序查找的方法;另一种是在顺序查找的方法进行改进,先大范围查找,再小范围顺序查找。并对这两种方法的执行效率进行对比。
代码如下:
/*
搜索区间内第uiNum个被占的位(位为1)
*/
#include "stdafx.h"
#include 
#include 
#include 
#include   
#include   

#define MAX_VALUE 6000000
typedef unsigned int UINT32;

/*
	方法1:采用顺序查找的方法
*/
UINT32 BitmapSearchNextBit1(UINT32 *puiBitmap, UINT32 uiStart, UINT32 uiEnd, UINT32 uiNum)
{
	UINT32 i = 0;
	UINT32 num = 0;
	UINT32 max_value = 0;
	if (!puiBitmap || uiEnd < uiStart)
		return (UINT32)-1;
	max_value = (sizeof(puiBitmap) / sizeof(puiBitmap[0])) * 32 - 1;

	if (uiStart > max_value)
		return (UINT32)-1;
	for (i = uiStart; i <= uiEnd; i++)
	{
		if (puiBitmap[i / 32] & (1UL << (i & 31)))//判断某一位是否为1
			num++;
		if (num == uiNum)
			return i;
	}
	return (UINT32)-1;
}
/*
	方法2:下面对顺序查找的方法进行改进,在一个整数长度内(32位)内采用顺序查找,即小范围内采用顺序查找;
	具体思路就是先以整形长度为单位,统计每个整形长度内1的个数,进而缩小查找范围,再采用以位为单位的顺序查找。
*/
/* 获取一个整数的二进制表示中1的个数 */
static UINT32 get_one_count(UINT32 ui_num)
{
	UINT32 i = 0;
	UINT32 sum = 0;
	while (i < 32)
	{
		sum += ((ui_num >> i) & 1UL);
		i++;
	}
	return sum;
}
/* 以位为单位进行小范围查找,获取指定范围内1的个数 */
static UINT32 BitmapSearchBitCount(UINT32 *puiBitmap, UINT32 uiStart, UINT32 uiEnd, UINT32 uiNum, UINT32 *count)
{
	UINT32 i = 0;
	if (!puiBitmap || uiEnd < uiStart)
		return (UINT32)-1;
	for (i = uiStart; i <= uiEnd; i++)
	{
		if (puiBitmap[i / 32] & (1UL << (i & 31)))// 判断某一位是否为1
		{
			(*count)++;
		}
		if (*count == uiNum) // 找到了,返回位索引
			return i;
	}
	return (UINT32)-1;
}
UINT32 BitmapSearchNextBit2(UINT32 *puiBitmap, UINT32 uiStart, UINT32 uiEnd, UINT32 uiNum)
{
	UINT32 count1 = 0;
	UINT32 count2 = 0;
	UINT32 count3 = 0;
	UINT32 temp_count = 0;
	UINT32 ret = 0;
	UINT32 index = 0;
	ret = BitmapSearchBitCount(puiBitmap, uiStart, (uiStart / 32 + 1) * 32 - 1, uiNum, &count1);
	if (ret != -1)
		return ret;
	for (index = uiStart / 32 + 1; index <= uiEnd / 32 - 1; index++)
	{
		temp_count = get_one_count(puiBitmap[index]);
		count2 += temp_count;
		if (count1 + count2 >= uiNum)
		{
			count2 -= temp_count;
			temp_count = 0;
			ret = BitmapSearchBitCount(puiBitmap, index * 32, (index + 1) * 32 - 1, uiNum - count1 - count2, &temp_count);
			if (ret != -1)
				return ret;
		}
	}
	temp_count = 0;
	ret = BitmapSearchBitCount(puiBitmap, uiEnd / 32 * 32, uiEnd, uiNum - count1 - count2, &temp_count);
	return ret;
}
int _tmain(int argc, _TCHAR* argv[])	
{
	struct timeb startTime, endTime;
	UINT32 ret = 0;UINT32 puiBitmap[(MAX_VALUE + 31) / 32];
	memset(puiBitmap,0,sizeof(puiBitmap));
	printf("%d\n", puiBitmap[2]);
	//置位
	puiBitmap[40 / 32] |= (1UL << (40 & 31));
	puiBitmap[150 / 32] |= (1UL << (150 & 31));
	puiBitmap[300 / 32] |= (1UL << (300 & 31));
	puiBitmap[607 / 32] |= (1UL << (607 & 31));
	puiBitmap[600000 / 32] |= (1UL << (6000000 & 31));
	//复位
	//puiBitmap[40 / 32] &= ~(1UL << (40 & 31));
	ftime(&startTime);
	int i = 0;
	while (i < 10)
	{
		//ret = BitmapSearchNextBit1(puiBitmap, 20, 600, 1);
		printf("%d\n", ret);
		//ret = BitmapSearchNextBit1(puiBitmap, 0, 280, 2);
		printf("%d\n", ret);
		//ret = BitmapSearchNextBit1(puiBitmap, 20, 400, 3);
		printf("%d\n", ret);
		//ret = BitmapSearchNextBit1(puiBitmap, 20, 607, 4);
		//printf("%d\n", ret);ret = BitmapSearchNextBit1(puiBitmap, 20, 6000000, 5);
		//printf("%d\n", ret);i++;
	}
	ftime(&endTime);printf("cost time1=%d\n", (endTime.millitm - startTime.millitm) + (endTime.time - startTime.time) * 1000);
	printf("//\n");
	ftime(&startTime);
	i = 0;
	while (i < 10)
	{
		//ret = BitmapSearchNextBit2(puiBitmap, 20, 600, 1);
		printf("%d\n", ret);
		//ret = BitmapSearchNextBit2(puiBitmap, 0, 280, 2);
		printf("%d\n", ret);
		//ret = BitmapSearchNextBit2(puiBitmap, 20, 400, 3);
		printf("%d\n", ret);
		//ret = BitmapSearchNextBit2(puiBitmap, 20, 607, 4);
		printf("%d\n", ret);
		ret = BitmapSearchNextBit2(puiBitmap, 20, 6000000, 5);
		//printf("%d\n", ret);i++;}
		ftime(&endTime);
		printf("cost time2=%d\n", (endTime.millitm - startTime.millitm) + (endTime.time - startTime.time) * 1000);
		system("pause");
		return 0;
}
 
   
 
   
运行结果如下图: 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
  
OJ-位图算法_第1张图片
可见经过改进后算法在查找速度上有所提升。方法1程序简单,方法2实现复杂,在小范围内查找时两种方法没差别,在大范围内查找才会有所区别。

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