在这篇文章中,我们探讨了2个变量的互换问题。我们介绍了不同的方法,包括使用第三个变量进行交换,使用算术运算、XOR、宏等等,以及它们的优点和缺点。
目录
- 互换简介
- 使用第三个变量
- 使用算术运算符+和-
- 使用算术运算符*和/
- 使用位数XOR运算符^
- 使用宏
- 其他方法
- 使用文件作为缓冲区
- 使用命令行相关变量作为缓冲区
交换的介绍
首先,我们应该对交换有一个概念。
其基本思想是将一个变量的值转移到另一个变量上,然后将第二个变量的值放到第一个变量上。
例子:
a = 6
b = 3
swap(a,b) //using a swap function
print("%d", a) //3
print("%d", b) //6
请注意,变量a和b的值在互换后是互换的。
使用第三个变量
我们创建一个第三变量temp或临时变量,并把它的值作为其中一个变量分配给它。(例如:b)
这就创建了一个b变量的副本。
现在你可以将b赋值给另一个变量,例如a,而不用担心b会因为a的赋值而丢失,因为它已经存储在临时变量中了:
a = 6
b = 3
temp = b
b = a
a = temp
print("%d", a) //3
print("%d", b) //6
注意
许多新来的人对为什么这一行
a = b
不起作用。
毕竟a=b与数学中的b=a是一样的。对吗?
在数学中可能是一个有效的声明,但在计算机中对变量的作用却不一样。
在计算机中,变量是容纳数值的容器,它们不是数值本身。像a = b这样的语句会使存储在容器a中的值等于容器b中的值。
但存储在容器b中的值将是相同的。
使用操作符+和-
这种方法很聪明,不用我们创建另一个变量就能得到结果。
不过这种方法对于大的数值可能会导致算术溢出(如果第一步超过了分配的内存):
a = 6
b = 3
a = a + b;
b = a - b;
a = a - b;
print("%d", a) //3
print("%d", b) //6
你也可以使用+和-运算符,以稍微不同的
方式
交换变量
a = b - a;
b = b - a;
a = b + a;
或者你可以这样做,以达到紧凑的效果:
a = (a + b) - (b = a);
使用运算符*和/
如果一个或两个变量都含有0,这个方法就不起作用了。
对于大数的乘法,它也有算术溢出的风险:
a = 6
b = 3
a = a * b;
b = a / b;
a = a / b;
printf("%d", a) //3
print("%d", b) //6
或者如果你想用简短的方法来做:
a = (a * b) / (b = a);
如果第一个变量(上例中的a)为0,它将显示未定义的行为。
使用逐位XOR (^)
要理解这个方法,可以把XOR想成是当数字0和1的位数不相同时切换的东西。
我们首先将两个变量的XOR存储在第一个变量中,然后再将它们切换回来,用于存储变量中的原始值:
a = 6
b = 3
a = a ^ b;
b = a ^ b;
a = a ^ b;
print("%d", a) //3
print("%d", b) //6
这种方法特别优雅,因为我们只用一个运算符就能交换变量,而不必再创建另一个变量。
你可以通过这样做使上面的代码更紧凑一些:
a ^= b;
b ^= a;
a ^= b;
或者如果你想更进一步:
a ^= b ^= a ^= b;
注意
当使用指向变量的指针时,如果两个指针都指向同一个变量,上述方法2、3和4将会失败。
例子
如果一个交换两个变量的函数接受两个变量的地址,那么像swap(&a, &a);这样的调用应该不会对变量a的值产生影响,但是在上述方法中(除了第三个变量方法),变量将存储不正确的值。
所以,我们首先需要检查这两个指针是否完全相同。
如果你想交换两个指针,一个很好的例子就是这样做:
void swap(int *x, int *y) {
if(a != b) { // Checking that x and y are not pointing to the same location
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
}
使用宏
宏是一段代码,它被宏的值所取代。宏是由#define指令定义的:
#define SWAP(a, b, Type) Type temp = a; a = b; b = temp;
int main() {
int a1 = 6, b1 = 3;
SWAP(a1, b1, int);
printf("After swapping: a1 = %d, b1 = %d", a1, b1); //After swapping: a1 =3, b1 = 6
return 0;
}
这种方法的好处是你可以对int、char、float等使用同一个SWAP()函数。
在GCC中,我们可以使它更加通用:
#define SWAP(x, y) typeof(x) temp = x; x = y; y = temp;
如果你经常使用swap函数,这个方法就很好,
在竞争性编程中也很有帮助,因为你必须要快。
其他方法
这些方法纯粹是出于理论上的考虑,
在大多数情况下使用这些方法是不可行的。
使用一个文件缓冲区
在这个方法中,我们将把a的值写在一个文件(temp.txt)中,然后再把b的值赋给它。
然后b扫描temp.txt的值,它就被分配了:
FILE *fp;
fprintf(fp = fopen("temp.txt", "w"), "%d", a);
fclose(fp);
a = b;
fscanf(fp = fopen("temp.txt", "r"), "%d", &b);
fclose(fp);
使用一个与命令行有关的变量作为缓冲区
我们使用一个命令行参数来交换值:
int main(int argc, char **argv) {
int a = 10, b = 5;
argc = a;
a = b;
b = argc;
printf("After swapping: a = %d, b = %d", a, b);
return 0;
}
结论
交换两个变量是算法中最常用的方法之一。你可以根据情况使用,根据情况考虑问题陈述,资源限制等
问题
浏览一下这个C++代码:
#include <stdio.h>
int main() {
int a = 6;
int b = 3;
a = b;
printf("%d, %d",a,b);
return 0;
}
上述代码的输出将是什么?
3, 3
3, 6
6, 3
编译错误
阅读 "使用第三个变量 "的说明
通过OpenGenus的这篇文章,你一定对交换两个变量有了深刻的认识,并能根据你的使用情况选择最佳技术。