三次异或交换数字
三次异或交换数字
void swap(int * restrict x, int * restrict y) { if (x == y) return; *y = *x ^ *y; *x = *x ^ *y; *y = *x ^ *y; // *y ^= *x ^= *y ^= *x; }
三种证明方式:
- 将所有可能写出来
只考虑一位的情况,可以看出三次异或后,位交换了。而整数也是多个位组成的,自然可以交换。
-
从正常交换的过程思考
正常交换数值时,需要一个值来保持中间变量。虽然没有直接声明一个变量来保持,但其实
y
就已经作为中间变量了。我将作为中间变量的y
写作y'
。第一次异或:
y'
保存了x
与y
不同的位(异或就代表着不同);
第二次异或:一个位异或0
值不变,异或1
则取反。此时y'
中保存着原来的y
不同于x
的位,所以y'
将x
中不同于y
的位都取反了,x
也就变成了y
;
第三次异或:x
现在是y
了,成功交换了。那么将y
中不同于x
的位取反(仍然通过y'
),y'
也就变成了x
。 -
列表写逻辑值
取
*x = a, *y = b
虽然思路很巧妙,但是异或开销大,比传统的交换慢上很多。
实际上,可以用加减代替异或
void swap(int * restrict x, int * restrict y) { if (x == y) return; *y = *x - *y; *x -= *y; *y += *x; // *y += *x -= *y = *x - *y; }
使用加减的交换过程比较好验证,也有其他更多写法,总之是三步完成交换。不过使用加减会出现溢出问题。
本文作者:violeshnv
本文链接:https://www.cnblogs.com/violeshnv/p/16831723.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步