2个变量互换的不同方法(附实例)

97 阅读5分钟

在这篇文章中,我们探讨了2个变量的互换问题。我们介绍了不同的方法,包括使用第三个变量进行交换,使用算术运算、XOR、宏等等,以及它们的优点和缺点。

目录

  1. 互换简介
  2. 使用第三个变量
  3. 使用算术运算符+和-
  4. 使用算术运算符*和/
  5. 使用位数XOR运算符^
  6. 使用宏
  7. 其他方法
    1. 使用文件作为缓冲区
    2. 使用命令行相关变量作为缓冲区

交换的介绍

首先,我们应该对交换有一个概念。

其基本思想是将一个变量的值转移到另一个变量上,然后将第二个变量的值放到第一个变量上。

例子:

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的这篇文章,你一定对交换两个变量有了深刻的认识,并能根据你的使用情况选择最佳技术。