常用操作交换两个数的值
常用的交换两个数值的方法一般是采用第三个变量,这种方法简单易懂,用代码举例
int main()
{
//交换两个整形变量
int a = 3;
int b = 5;
int c = 0;//第三个变量
printf("交换前:a=%d b=%d\n", a, b);
c = a;
a = b;
b = c;
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
这么简单的题目肯定不是面试官想要的,所以就引出了这次要讨论的内容:在不使用第三个变量的前提下交换两个变量的值。稍加思索也能给出解决方案
不使用第三变量
int main()
{
int a = 3;
int b = 5;
printf("交换前:a=%d b=%d\n", a, b);
a = a + b;//a放的是和,b还是原来的b
b = a - b;//b得到原来的a
a = a - b;//a得到原来的b
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
这种算法看起来是解决了问题,但是还存在缺陷,使用加减法会导致溢出从而报错,出现隐患;还有进一步优化的空间 。
最优解决方案:异或
首先要介绍一个运算符^,按位异或运算符:相同为0不同为1
int main()
{
int a = 3;//二进制:011
int b = 5;//二进制:101
printf("交换前:a=%d b=%d\n", a, b);//^是按位异或:相同为0不同为1
//
a = a^b;//此处a=110 b=101
b = a^b;//此处a=110 b=011
a = a^b;//此处a=101 b=011
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
注:括号内为二进制数值,标红的为中间值。
被交换数的值为3(011)和5(101),中间值是6(110),这样程序可看作:
a=3(011),b=5(101);
3(011)^5(101)=6(110)=a,此时:a=6(110),b=5(101);
6(110)^5(101)=3(011)=b,此时:a=6(110),b=3(011);
6(110)^3(011)=5(101)=a,此时:a=5(101),b=3(011);
异或交换的原理:
两个被交换数异或会得到一个中间值,两个被交换数中的任意一个和中间值异或就会得到另一个被交换数。
初始的状态: 此时a=被交换数3,b=被交换数5
第一次异或:3和5异或得到中间值6放到a里;
此时a=中间值6,b=被交换数5
第二次异或:5和中间值6异或得到另一个被交换数3放到b内,这时已经交换了一半;
此时a=中间值6,b=被交换数3
第三次异或:3和中间值6异或得到另一个被交换数5放到a内,此时交换完成;
此时a=被交换数5,b=被交换数3