交换两个数是每个初学者在学习cin
语句时的必学这知识。本帖子从交换两数的实现、交换两数的作用两方面讲解。
交换两数的实现
让我们想象一下,我们面前有一杯红墨水和一杯蓝墨水,我们要如何让他交换?
直接把蓝墨水倒进红墨水是不行的,所以我们要另外拿出一个瓶子。将蓝墨水倒入该瓶子中,再将红墨水倒入蓝墨水的瓶子中,再将蓝墨水倒入红墨水的瓶子中。
如果把蓝墨水看做其中一个变量,红墨水看做另一个变量,那么我们就可以写出交换两变量的算法了。
代码如下:
c=a;
a=b;
b=c;
你以为这就完了?
以下均为拓展。
上个高级的。
a+=b;
b=a-b;
a-=b;
此代码中含有危险行为,请勿轻易模仿。
先简单分析一下该代码:
执行第一行代码时:a=原a+原b b=原b
执行第二行代码时:a=原a+原b b=原a+原b-原b=原a
执行第三行代码时:a=原a+原b-b=原a+原b-原a=原b b=原a+原b-原b=原a
最后我们发现:现在的a刚好等于原来的b,现在的b刚好等于原来的a。
为什么说此代码中含有危险行为呢?原因如下:
- 会增加代码运行的时间。
- 在计算时会有溢出的风险。
但它也不是没有好处,这段代码无需额外的空间。
如果再提一种无需额外空间的代码,就要提到位运算了。
我们今天只了解一种:按位异或运算。
什么是按位异或呢?
异或:只有两个值不同时才为 1,其余状态为0。
要求按位异或时可以使用转二进制+竖式的方法.
例:求7
和11
的按位异或。
第一步:转二进制
7_{10}=111_2
11_{10}=1011_2
第二步:竖式计算
1011
0111
----
1100
第三步:转十进制
1100_2=12_{10}
所以7按位异或11为12。
异或有三大运算律,分别是:
- 交换律: a⊕b=b⊕a 。
- 结合律: (a⊕b)⊕c=a⊕(b⊕c) 。
- 自反律: a⊕b⊕a=b
异或在C++中为^
。
回归正题:如何用异或交换两个数。
a^=b^=a^=b;
看完代码后,你是不是非常惊讶:
如此短,如此简洁!
如何理解这段代码呢?
把它拆开,从右往左拆。
a^=b;
a^=b^=a;
a^=b;
b^=a;
a^=b;
再分析一波:
执行第一行代码时:a=原a^原b b=原b
执行第二行代码时:a=原a^原b b=原a^原b^原b=原a
(交换律+自反律)
执行第三行代码时:a=原a^原b^b=原a^原b^原a=原b b=原a^原b^原b=原a
(自反律)
好神奇啊!
很好,这就完了,这真的就完了。
与第二种方法不同的是这段代码不会溢出。
现在,给大家分享一下swap
函数的用法。STL大法好
swap
是一种及其常用的内置库函数(简称STL),使用方法如下:
swap(交换变量1,交换变量2);
例:
cin>>a>>b;
swap(a,b);
cout<<a<<" "<<b;
输入:20 10
输出:10 20
虽然但我觉得这样不好玩
交换两数的作用
交换在排序中有极大的作用。
例:
冒泡排序
for(int i=n;i>=2;i--){
for(int j=1;j<=i-1;j++){
if(a[i]<a[j]){
a[i]^=a[j]^=a[i]^=a[j];
}
}
}
(这几个月都用sort
,手写排序只知道冒泡了,我太菜了)
这下是真的写完了。