桶排序对于负数的处理

关于桶排序的算法思想就不再叙述了,目前桶排序主要用于在O(n)的时间内处理正数的排序问题, 然而一旦遇到负数问题,就只能把数分成两堆,对正负数分开去排序,这样无疑比较麻烦。今天我做了一个桶排序的题,对于输入都是32位整形数列进行桶排序,值想到了一个可以同时处理正负数的算法。

通常我们的输入都是十进制数,桶排序都是设置为10个桶,从后向前每次对每一个位进行排序,这样虽然是O(n),但是除法操作会占用大量的时间。我的改进思路是将桶设置为16个,即2^4个桶,32位的int型整数看做16进制是8位,最高位是符号位,这样可以用移位操作代替除法操作,大大提高了效率。桶排序的空间复杂度是O(n) ,即需要开辟新数组存储所有的数据,桶的数量不影响空间复杂度。代码如下:

void bucket_sort(vector<int>& nums){
		vector<vector<int>> bucket(16, vector<int>());
		//第一轮,将数组按照最低四位2进制数存入所有的桶中
		for (auto i : nums){
			bucket[i & 15].push_back(i);
		}
		//循环七轮,进行桶排序
		for (int i = 1; i < 8; i++){
			vector<vector<int>> bucket2(16, vector<int>());
			//计算移位和掩码
			int shift = i * 4;
			int mask = 0xf<< shift;
			for (auto v : bucket)
				//注意 C++ unsigned的右移是逻辑右移,前面不补0
				for (unsigned num : v)
					bucket2[(num&mask) >> shift].push_back(num);
			//每轮之后交换原桶和临时桶
			swap(bucket, bucket2);
		}
		//排序之后,交换正负数的位置
		int pos = 0;
		for (int i = 0; i < 8; i++) swap(bucket[i], bucket[i + 8]);
		for (auto v : bucket)
			for (auto i : v)
				nums[pos++] = i;
	}
唯一需要说明的就是,排序之后,由于负数的符号位是1,正数的符号位是0,所以0-7个桶存放的是正数,8-15个桶存放的是负数;除此之外,正数是从小到大排列的,负数由于是补码存放,其绝对值为取反之后再加1,所以负数是按照绝对值从大到小排列的,即负数也是从小到大排列的。所以只需要把0-7桶放到8-15桶的后面,即可完成排序。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值