如何交换两个数(编程技巧与知识讲解day1)

交换两个数是每个初学者在学习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. 会增加代码运行的时间。
  2. 在计算时会有溢出的风险。

但它也不是没有好处,这段代码无需额外的空间。
如果再提一种无需额外空间的代码,就要提到位运算了。


我们今天只了解一种:按位异或运算。
什么是按位异或呢?

异或:只有两个值不同时才为 1,其余状态为0。
要求按位异或时可以使用转二进制+竖式的方法.
例:求711的按位异或。
第一步:转二进制
7_{10}=111_2
11_{10}=1011_2
第二步:竖式计算

1011
0111
----
1100

第三步:转十进制
1100_2=12_{10}
所以7按位异或11为12。

异或有三大运算律,分别是:

  1. 交换律a⊕b=b⊕a
  2. 结合律(a⊕b)⊕c=a⊕(b⊕c)
  3. 自反律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,手写排序只知道冒泡了,我太菜了)
这下是真的写完了。

点赞

2 个赞

swap呢

2 个赞

我不想写到帖子里,因为不好玩

1 个赞

写了

1 个赞

因为不好玩,所以写了?

2 个赞

不能说一点没用吧,只能说没有一点用(doge

2 个赞

是的,所以我在“交换两数的作用“这一部分中不知道写什么。

1 个赞

其实我是准备写的,后来写着写着就忘了。

1 个赞

还有赞呢?

1 个赞

%%%膜拜大佬

别到处乱膜。

1 个赞

我才学到基础算法。

1 个赞

稍微会点普及。

1 个赞

建议多%

总结

zky:I AK IOI
me: IOI AK ME

1 个赞

me: IOI1994 D1T1 AK ME

1 个赞

1 个赞

想试试的话点发送

1 个赞

1 个赞