关于swap的几点发散思维(1)

(1)    不用中间变量的交换

 

不用中间变量,这个起初觉得不太现实,但是经过一些技巧,却可以很轻松的实现。同样是3行代码,可以代替老套的

temp = a; a = b; b = temp;        //swap a and b

这三行。

 

新的解决方案嘛,可以相当巧妙的,使用了位运算中的异或运算符。

代码也是只有三行:

a ^= b; b ^= a; a ^= b;

如果你是第一次看到这种代码,可能有点晕。不过没关系,稍微解释相信聪明的你可以很快就明白的。

 

因为是位运算,我们就不得不从位的角度(bitwise)去理解这个问题。

首先,我们要知道异或的作用。

异或嘛,个人觉得,有点像汉语的“抑或”。通常我们说这个词的时候,是表示两种情况中的一种。

如果从逻辑学的角度去分析,那么,就是只有两个逻辑子句,有且只有一个为true的时候,整条语句才为true,否则均为false

那么,我们可以很容易得到下面的真值表:

 

条件a

条件b

a异或ba^b

true

true

false

true

false

true

false

true

true

false

false

false

 

从二进制的角度去理解,true代表1false代表0。那么我们可以很容易地得到下面的结论:

任何位与0进行异或运算,均得到自身,与1进行异或运算,均得到自己的补位。

那么用x表示一个二进制位(bit),那么上面的结论就是 x^0=xx^1=~x

 

现在,我们继续稍稍研究下其他几个结论,也是很容易推出的。

任何数与自身进行异或,均为0 。即 a^a=0

 

而且,异或运算具有交换性,即a^b = b^a

 

异或运算具有结合性,即a^b^c=b^c^a=a^c^b

(其实可以得到六个等式,不过其他的已包含在交换性内,不在列出)

 

呵呵,是不是很简单?

上面的既然都明白了,现在就很轻松地可以理解那种奇异的swap了。

我们不妨把最初的ab分别命名为a1b1。把交换后的ab命名为a2b2

那么我们的目的就是让a2=b1b2=a1

 

首先是a^=b

它代表a=a^b,那么这时候得到的a,既不是我们想要的a2,更不是b2,我们姑且叫它a3吧。

 

 

然后b^=a,就是b=b^a

这里的a是刚才的a3,那么就是计算b1^a3。而a3又是a1^b1,那么我们就得到了b^a其实是b1^a1^b1

嘿……刚才的一些性质发挥作用了,先改变下结合顺序,得到b1^b1^a1,然后b1^b10,那么就是0^a1,还是a1,所以刚才b^=a,已经得到b2

 

 

第三句,a^=b,即a=a^b,这里的aa3bb2

那么,我们展开,b2可以认为是a1的值,那么等式右边的a^b其实就是a1^b1^a1,同上,很容易得到最后a被赋值为b1

 

嘿嘿,同样达到了我们的目的。

 

接下来,稍微值得思考一下的是,是不是所有交换都可以这么实现呢

 

呃,其实呢,起初,按我的想法呢,只要是值类型(Value Type),就都可以的。我特意在J2SE的环境下写了相关代码进行测试,发现小数类型(double以及float不可以。编译错误提示为:

The operator ^= is undefined for the argument type(s) double, double

其他的,无论是shortlongintboolean以及char都作过测试,均没问题。

 

进一步修改,做测试,发现不同类型也可以实现交换。比如如下代码:

              int a=-5;

              long b=43;

              System.out.println(a+"/t"+b);

              a^=b;

              b^=a;

              a^=b;

        System.out.println(a+"/t"+b);

依旧没问题,可见Java编译器已经很成熟地做了对不同长度数据类型(包括有符号数的自动位扩充)的合适处理。

 

最后想说下, 个人觉得有以下好处:

第一嘛,可以炫耀你的代码,哈哈,因为不少人如果首次看到这三行,估计要想半天是怎么回事。

第二嘛,没有中间变量,当然节省了那么一点栈空间。

第三嘛,因为可以令不同类型的Value Type 实现交换(小数除外),那么……总比为了想一个合适的temp类型而煞费苦心要好的多。

 

……

 不过也有不少局限,其中速度上比中间变量的交换稍微错了点。(可以使用大量循环累积时间来计时断定)

 

 

 

到此为止吧,呵呵,这个是第一个关于swap的发散思维,后面还有更多呢!谢谢你的支持!

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值