位图运算(c++)

【题目】

有很多不重复的整数, 其中最大值不超过 40 亿, 最小值是 0. 要求判断某个指定的整数, 是否在这个集合中. 

最快的算法:

位图算法。

使用两个字节,表示16个数(0-15)的状态(1表示有,0表示没有)。

1514131211109876543210
000000000000000

如果存入的数据为【12,9,5,3,1】,则存储为:

1514131211109876543210
0001001000101010

代码:
#include <iostream>
#include <windows.h>
using namespace std;
void init(char* data, int len)
{
	//假设:存入的数据为能被3整除的数
	unsigned int n = len * 8; //一共有n个数据
	for (unsigned int i = 0;i < n;i++)
	{
		if (i % 3 == 0)
		{
			char* p = data + i / 8;  //求出i所在字节
			*p = *p | (1 << (i % 8)); 
		}
	}
}
bool check(char* data, int len, int value)
{
	//定位到指定的字节
	char* p = data+value / 8;
	//判断这个字节中指定的位是否为1
	bool ret = *p & (1 << (value % 8));
	return ret;
}
int main(void)
{
	unsigned int n = 4000000;  //位数
	int len = n / 8 + 1;     //考虑只有7位的情况
	char* data = new char[len];  //分配一块内存空间
	memset(data, 0, len); //清零
	//装载数据集合(只需要装载一次)
	init(data, len);

	while (1)
	{
		cout << "请输入要检测的数:[输入-1结束]" << endl;
		int value;
		cin >> value;
		if (value == -1)
		{
			break;
		}
		if (check(data, len, value))
		{
			cout << value << "在数据集合中" << endl;
		}
		else
		{
			cout << value << "不在数据集合中" << endl;
		}
	}
	delete data;
	system("pause");
	return 0;
}

补充:

位或 |

        0 | 0 0

        0 | 1 1

        1 | 0 1

        1 | 1 1

        对应位, 都是 0, 结果才是 0 只要有一位是 1, 结果就是 1

        0 | x x

        // 00001000

        // 00000011

        // 00001011

        cout << " 8 | 3 = " << (8 | 3) << endl;

位与 &

        0 & 0 0

        0 & 1 0

        1 & 0 0

        1 & 1 1

        对应位, 都是 1, 结果才是 1

        // 00001000

        // 00000011

        // 00000000

        cout << " 8 & 3 = " << (8 & 3) << endl;

<< 左移

        右边的位用 0 来填充, 移动超出左边边界的位则直接抛弃。 向左移动 n 个位置,就等同于乘 

        以 2 的 n 次方

        只适用于: int/short/long/char 等定点数类型(float/double 浮点数类型不能使用)

        // 00001000

        // 01000000

        cout << (8<<3) << endl;  //8*2*2*2 = 64

<think>好的,我现在需要帮助用户了解C++中位运算的使用方法和示例。首先,我应该回顾用户提供的引用内容,看看有哪些相关的信息可以整合进去。用户给出了五个引用,涉及到位运算的不同方面,比如或运算、异或运算位图应用以及位移操作等。 首先,我需要明确位运算的基本操作符,包括按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)和右移(>>)。每个操作符的用途和示例都需要详细说明,同时结合用户提供的引用中的代码示例,这样能让回答更具体。 例如,引用[1]提到了或运算C++示例,可以用于设置特定比特位。引用[2]和[3]展示了异或在加法算法和找出只出现一次的数字中的应用。引用[4]中的位图思想用于检测字符串是否唯一,这可以用位掩码和或运算来实现。引用[5]提到了位移运算符的用途,比如左移实现乘2的幂次。 接下来,我需要将这些知识点组织起来,分门别类地解释每个位运算符的作用,并给出对应的示例代码。要注意用户提到的系统级指令,比如行内数学表达式用$...$,独立公式用$$...$$,但用户提供的引用中并没有数学公式,所以可能需要根据情况添加,比如解释异或的性质时可以用数学表达式。 另外,用户要求生成相关问题,我需要根据内容设计几个相关的问题,比如位运算的常见应用场景、如何用位运算优化代码等。 在编写过程中,要确保语言简洁,结构清晰,符合中文表达习惯。同时,引用需要自然地插入到相关内容末尾,如引用[^1]、[^2]等。需要检查每个引用对应的内容是否正确,比如引用[2]是关于使用异或和与运算实现加法,引用[3]是关于异或的恒等律应用。 最后,确保所有代码示例使用正确的C++语法,并符合用户提供的引用中的代码风格。例如,引用[4]中的位图实现需要详细说明每个步骤的作用,如何通过位运算判断字符是否重复出现。 总结来说,我需要分步骤介绍每个位运算符,结合用户提供的引用中的示例,说明其实际应用,并确保回答结构清晰,引用正确,同时生成相关问题以帮助用户进一步学习。</think>### C++运算详解 位运算直接操作二进制位,常用于高效处理整数、状态压缩、位掩码等场景。以下是常见位运算符及示例: --- #### 一、基本运算符与用途 1. **按位与(`&`)** 对应位同为1时结果为1,否则为0。 **用途**:提取特定位、判断奇偶性。 **示例**: ```cpp int a = 5; // 二进制 0101 int b = 3; // 二进制 0011 int c = a & b; // 结果 0001(十进制1) ``` 2. **按位或(`|`)** 对应位至少一个为1时结果为1。 **用途**:设置特定位。 **示例**(引用[1]): ```cpp int bit = 0; bit |= (1 << 3); // 将第3位设为1(二进制1000) ``` 3. **按位异或(`^`)** 对应位不同时结果为1。 **性质**: - 恒等律:$a \oplus 0 = a$ - 自反性:$a \oplus a = 0$ **用途**:交换变量、找唯一数、加法模拟。 **示例**(引用[3]): ```cpp int arr[] = {1, 2, 3, 2, 1}; int num = 0; for (int x : arr) num ^= x; // 结果3(唯一出现一次的数) ``` 4. **按位取反(`~`)** 所有位取反。 **示例**: ```cpp int a = 5; // 0101 int b = ~a; // 1010(补码形式,实际值为-6) ``` 5. **左移(`<<`)** 所有位左移,低位补0。 **用途**:快速计算$2^n$(引用[5])。 **示例**: ```cpp int a = 3; // 0011 int b = a << 2; // 1100(十进制12,即3×2²) ``` 6. **右移(`>>`)** 所有位右移,高位补符号位(算术右移)或0(逻辑右移)。 **示例**: ```cpp int a = -8; // 1111...1000 int b = a >> 2; // 1111...1110(十进制-2) ``` --- #### 二、实际应用场景 1. **快速加法**(引用[2]) 通过异或和与运算模拟进位: ```cpp int getSum(int a, int b) { while (b) { int carry = (a & b) << 1; // 计算进位 a = a ^ b; // 无进位相加 b = carry; } return a; } ``` 2. **位图压缩状态**(引用[4]) 用整数比特位表示字符是否出现: ```cpp bool isUnique(string s) { int bit = 0; for (char ch : s) { int idx = ch - 'a'; if ((bit >> idx) & 1) return false; // 判断是否重复 bit |= (1 << idx); // 标记已出现 } return true; } ``` 3. **权限控制** 使用位掩码管理权限: ```cpp const int READ = 1 << 0; // 0001 const int WRITE = 1 << 1; // 0010 int user_permission = READ | WRITE; // 赋予读写权限 bool canWrite = user_permission & WRITE; // 检查写权限 ``` --- #### 三、注意事项 - **优先级**:位运算符优先级通常低于算术运算符,建议用括号明确顺序。 - **符号位**:右移操作对有符号数的结果依赖编译器实现。 - **可读性**:复杂位运算需添加注释说明逻辑。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值