这段代码实现了一个非常经典且巧妙的位运算算法——莫顿码(Morton Code)生成,也称为位交织(Bit Interleaving)。它常用于空间填充曲线(Z-order curve),将多维坐标压缩成一维。
1. 代码逻辑详细分析
变量处理过程
代码的核心在于对 x 和 y 进行相同的“拉伸”操作,然后合并。
- 输入限制:$x, y$ 均不超过 15,即它们最多占用 4 位二进制位($0 \sim 1111_2$)。
- 拉伸操作(以 $x$ 为例):
x = (x | x << 2) & 0x33;0x33的二进制是0011 0011。- 原本的
abcd变为00ab 00cd。
x = (x | x << 1) & 0x55;0x55的二进制是0101 0101。- 将
00ab 00cd进一步拉伸为0a0b 0c0d。
- 结果:$x$ 的二进制位之间被插入了一个 0。
- 合并操作:
unsigned short z = x | y << 1;- 拉伸后的 $x$ 是
0 x3 0 x2 0 x1 0 x0 - 拉伸后的 $y$ 左移一位是
y3 0 y2 0 y1 0 y0 0 - 按位或之后,结果 $z$ 为:
y3 x3 y2 x2 y1 x1 y0 x0。 - 本质:将 $y$ 和 $x$ 的二进制位交错排列,组合成一个 8 位的整数。
2. 题目解析
判断题
-
删去 unsigned,程序行为不变。
- 答案:A (正确)
- 分析:
short在 C++ 中至少 16 位。输入最大为 15,中间拉伸后的最大值是0x55(85),最终结果 $z$ 最大是 255。这些数值都在有符号short(-32768 到 32767)的范围内。只要不涉及最高位(符号位)的移位运算,short和unsigned short在此范围内的表现是一致的。
-
将 short 改为 char,程序行为不变。
- 答案:B (错误)
- 分析:在许多平台上
char是有符号的且只有 8 位(-128 到 127)。如果输入 $x=15, y=15$,计算出的 $z$ 应该是 255。如果使用char,255 会溢出变成 -1,导致输出行为改变。
-
程序总是输出一个整数“0”。
- 答案:B (错误)
- 分析:显然不是,只要输入不全为 0,输出就不为 0。
-
当输入为 2 2 时,输出为 10。
- 答案:B (错误)
- 分析:
- $x = 2 \to (0010)_2 \to$ 拉伸后为 $(00001000)_2$(错误,应该是 $00000100_2 = 4$)。
- $y = 2 \to (0010)_2 \to$ 拉伸后为 $4$。
- $z = x | (y << 1) = 4 | 8 = 12$。输出应为 12。
-
当输入为 2 2 时,输出为 59。
- 答案:B (错误)
- 分析:同上,计算结果是 12。
单选题
- 当输入为 13 8 时,输出为( )。
- 答案:B (209)
- 分析:
- $x = 13 = (1101)_2$。
- $y = 8 = (1000)_2$。
- 交织公式:$z = (y_3 x_3 y_2 x_2 y_1 x_1 y_0 x_0)_2$。
- 代入:$y$ 的位是 $(1, 0, 0, 0)$,$x$ 的位是 $(1, 1, 0, 1)$。
- 得到 $z = (11 01 00 01)_2$。
- 转换为十进制:$128 + 64 + 16 + 1 = 209$。
3. 复杂度与总结
- 时间复杂度:$O(1)$。所有的位运算都是常数步完成。
- 空间复杂度:$O(1)$。
- 应用场景:这种技术在图像处理、多维空间索引(如点云数据处理、游戏引擎的空间划分)中非常重要,因为它能让二维空间中位置靠近的点,在一维编码上也尽可能靠近。
—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com