两只箱子。左边箱子装着一只猫,右边箱子放着一只兔子。如何让猫和兔子交换位置,变为兔子装在左边箱子里,猫放在右边箱子呢?
这是一个很简单的问题。你问我的话,我给出的办法简单,就两步。
第一步,把兔子放进左边箱子;
第二步,把猫猫放进右边箱子。
你还能想出更简单的方法来吗?
衍生出来的问题就是,设定有两个对象A1和A2, A1的值为V1, A2的值为V2。然后求如何交换两对象的值,使其A1的值为V2,A2的值为V1。从程序代码层级加以实现。
解法一:通过一个临时的对象来实现值的交换。这是每本编程入门教科书都会提到的解法。
#include <iostream>
void swap(int &v1, int &v2)
{
int t = v1;
v1 = v2;
v2 = t;
}
int main() {
int a1 = 42;
int a2 = 13;
swap(a1, a2);
std::cout << "a1: " << a1 << " a2: " << a2 << std::endl;
return 0;
}
解法二:闭门造车不如草船借箭。有没有现成的东东借来一用呢?还真有!在C 的标准库STL定义了一个通用函数swap。
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
string left_box = "pussy";
string right_box = "bunny"
swap(left_box, right_box);
std::cout << "left box: " << left_box
<< " right box: " << right_box
<< std::endl;
return 0;
}
解法三:数学魔法来啦。自定义一个函数swap。神奇藏在swap函数体里面。没有借助任何资源, 两对象交换了各自的值!
#include <iostream>
#include <string>
using namespace std;
//-----------------------------------------------------------------------------
// swap the two objects by a hacking trick with ^ operation (XOR)
// (a^b)^a = b
// (a^b)^b = a
//-----------------------------------------------------------------------------
template<typename T>
void swap(T &lhs, T &rhs)
{
if (lhs != rhs)
{
lhs = lhs ^ rhs;
rhs = lhs ^ rhs;
lhs = lhs ^ rhs;
}
}
int main() {
string left_box = "pussy";
string right_box = "bunny";
swap(left_box, right_box);
std::cout << "left box: " << left_box
<< " right box: " << right_box
<< std::endl;
}
神奇魔法依赖布尔代数中的一个结论。布尔代数中用^来表示异或运算。^的运算规则用如下图示说明。
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
由此容易推得一个神奇的结论:
(a^b)^a = b
(a^b)^b = a
你可以这么理解。a和b是两个物件,通过异或操作,a^b,形成合体;钥匙是a或者b,借助上面的结论,我们能完美地分别提取出藏在a^b合体中的a和b——用钥匙a,提取出b;用钥匙b,提取出a。
空谈误事。上代码。你看如下的代码中,swap函数体没有创建任何临时变量,没有借助库函数,只用了三次异或位运算^就让传入的两个对象的值互换了!
void swap(T &lhs, T &rhs)
{
lhs = lhs ^ rhs;
rhs = lhs ^ rhs;
lhs = lhs ^ rhs;
}
这不是一种魔法吗?数学就是这么神奇。
更多相关资料,敬请关注头条号“独角兽电波”。
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved