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′=a′−b=(a+b)−b=aa′′=a′−b′=(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+b−b′=a+b−a=b,然后swap就完成了
方法四
位运算也可以交换,这里我们会用到 异或(XOR) 的交换律、结合律和自反的性质。
void swap(int &a,int &b){
a ^= b;
b ^= a;
a ^= b;
}
第一步
a
′
=
a
⊕
b
a'=a \oplus b
a′=a⊕b
然后
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′=b⊕a′=b⊕(a⊕b)=b⊕b⊕a=a
最后
a
′
′
=
a
′
⊕
b
′
=
(
a
⊕
b
)
⊕
a
=
b
a''=a' \oplus b'=(a \oplus b) \oplus a =b
a′′=a′⊕b′=(a⊕b)⊕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;
}