你真的了解swap吗?


swap交换函数是一个非常非常接触的函数,也是每个初学者都会遇到的函数。近日我在问答区回答问题的时候,遇到了一种写法,让我眼前一亮。我决定深究一下。

常规方法

void swap(int &a,int &b){
	int temp;
	temp = a;
	a = b;
	b = temp;
}

这就是我们熟知的swap函数,也非常易于理解

方法二

void swap(int &a,int &b){
	a = a + b;  
    b = a - b;  
    a = a - b;
}

这就是我在问答区遇到的方法。说实话,我原来还真没有遇到过这样的写法,但是这种也很好理解。为了不混淆,下面我们会将改变过后的变量记为 x ′ x' x的形式
a ′ = a + b b ′ = a ′ − b = ( a + b ) − b = a a ′ ′ = a ′ − b ′ = ( a + b ) − a = b \begin{aligned} & a' = a + b\\ & b' = a' -b = ( a + b ) - b = a\\ & a'' = a' - b' = (a+b)-a=b \end{aligned} a=a+bb=ab=(a+b)b=aa=ab=(a+b)a=b
最后就得到了:
b ′ = a a ′ ′ = b \begin{aligned} & b' = a\\ & a'' = b \end{aligned} b=aa=b
这样就起到了交换的效果

方法三

void swap(int &a,int &b){
    a = a+b-(b=a);
}

这种方法实质上与第二种无异,但要更简便。由于括号的优先级最大,会最先执行 b ′ = a b'=a b=a然后就是 a = a + b − b ′ = a + b − a = b a = a+b-b'=a+b-a=b a=a+bb=a+ba=b,然后swap就完成了

方法四

位运算也可以交换,这里我们会用到 异或(XOR) 的交换律、结合律和自反的性质。

void swap(int &a,int &b){
    a ^= b;
    b ^= a;
    a ^= b;
}

第一步
a ′ = a ⊕ b a'=a \oplus b a=ab
然后
b ′ = b ⊕ a ′ = b ⊕ ( a ⊕ b ) = b ⊕ b ⊕ a = a b'=b \oplus a'=b \oplus (a \oplus b)=b \oplus b \oplus a = a b=ba=b(ab)=bba=a
最后
a ′ ′ = a ′ ⊕ b ′ = ( a ⊕ b ) ⊕ a = b a''=a' \oplus b'=(a \oplus b) \oplus a =b a=ab=(ab)a=b
交换就完成了

PS:有些教程会加一个条件判断就是a != b,也就是说代码为:

void swap(int &a,int &b){
	if(a!=b){
		a ^= b;
		b ^= a;
		a ^= b;
	}	
}

但这完全没必要,反正最后结果都是一样的。

我们可以简写为

void swap(int &a,int &b){
    a ^= b ^= a ^= b;
}

这两句是等效的,第二句的运算顺序是

a ^= (b ^= (a ^= b));

总结

后面三种方法固然巧妙,简洁。但是却只能交换像 整形、字符型 等等,但对于字符串这种就无能为力了。所以常规写法才是王道

template<typename T> 
void swap(T &a,T &b){
    T temp(a);
    a = b;
    b = temp;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

orbitgw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值