位图排序思想及代码实现

位图排序只适应于没有重复元素的排序。

思想

位图排序的核心思想是:每一位代表一个数字。下面我们用图示的方法进行具体介绍。
我们都知道1个整数占4个字节,1个字节有8位
现在我们定义 int i,则系统分配如下空间:
在这里插入图片描述
int i共有32位,可表示32个数字。
若我们定义int a[3],则系统分配如下空间:
在这里插入图片描述
int a[3]共有96位,可表示96个数字。
下面看每位是如何表示一个数字的
我们先看一个简单的例子: 18 4 26 3 5这三个数字为例。这三个数字里面最大的是26,所以我们申请一个整数空间int i即可。
第一步:先将所有的位清零
在这里插入图片描述
第二步:将要表示数字的对应位的值置1
在这里插入图片描述
这样我们就完成了数字用位的表示。
第三步:从最小位开始,若位上的值为1则进行输出,即可完成排序
上例输出的结果为:3 4 5 18 26.
下面我们看一下63 在空间中的表示.63/32+1=2。所以我们需要申请2个整数int a[2]。然后我们需要确定63所在的行与列
确定所在的行(右移5位)
63/32=1,所以在第一行。我们知道右移五位(2^5=32)相当于除以32,因为移位比除法的底层实现简单,所以我们用右移求行。
确定所在的列(&0x1F)
63%32=31,所以在第31列。同样我们可以用&0x1F实现。
表示结果如下所示:
在这里插入图片描述

代码

//位图排序

#include<stdio.h>
#include<time.h>


//c语言中定义一个局部变量数组时,若没有赋初值,则数组中的值是随机的。
//若定义全局变量时,则会自动赋值,如int a会赋值a为0.

#define   BITSPERWORD 32//一个整型数有4个字节,32位
#define   SHIFT 5//确定所在的行,除以32。(相当于右移5位)
#define   MASK 0x1F//确定所在的列,求余32.(相当于与0x1F进行与操作)
#define   N  100//对100个数进行位图排序
//只能排序0~100的数字

int a[1 + N / BITSPERWORD];//确定所需整数的个数。

void clear(int i)//可以省略。第i位清零。
{
	a[i>>SHIFT] &= ~(1 << (i & MASK));
	//i >> SHIFT;所在的行。
	//i&MASK;所在的列。
	//可以不可以:a[i>>SHIF]&=(0<<(i&MASK));
}

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

int test(int i)//判断i位置上是否有数
{
	return a[i>>SHIFT] & (1 << (i & MASK));
}

int main()
{
	int i;
	clock_t start, end;//检测运行时间的代码
	start = clock();//检测运行时间的代码
	for (i = 0; i < N; i++)
		clear(i);
	while (scanf_s("%d", &i) != EOF)
		set(i);
	for (i = 0; i < N; i++)
		if (test(i))
			printf("%d\n", i);
	end = clock();//检测运行时间的代码
	printf("运行所花费的时间是=%f\n", ((double)end - start) / CLK_TCK);//检测运行时间的代码
	return 0;
}

下面这个给你个我个人觉得好理解一点的代码


#include<iostream>

#define Bit 32
#define shift 5
#define mask 0x1F
#define N 1000
int a[1 + N / Bit];

void clear(int i)
{
	a[i >> shift] &= (0 << (i & mask));
}

void set(int i)
{
	a[i >> shift] |= (1 << (i & mask));

}

int test(int i)
{
	return a[i >> shift] & (1 << (i & mask));
}


void main()
{
	int i;
	for (i = 0; i < N; i++)
		clear(i);
	while (scanf_s("%d", &i) != EOF)
		set(i);
		for (i = 0; i < N; i++)
			if (test(i))
				printf("%d\n", i);
	
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值