如何在不使用临时变量或算术运算的情况下交换两个数字?

mr_*_*air 35 c c++ swap objective-c

此公式交换两个数字而没有临时变量,但使用算术运算:

a = (a+b) - (b=a);
Run Code Online (Sandbox Code Playgroud)

没有算术运算我该怎么办?我在想XOR.

小智 22

a=a+b;
b=a-b;
a=a-b;
Run Code Online (Sandbox Code Playgroud)

这很简单但有效....

  • 看起来它虽然包含一些算术运算符. (12认同)
  • @Mikhail:溢出将发生在'a = a + b`.然后在'b = ab`和'a = ab`处发生两次下溢,导致两个变量正确地交换值. (4认同)
  • 与xor示例不同,这也是溢出的. (3认同)
  • @displayName正确吗?在连续3次未定义行为之后,我将不再使用该词。 (2认同)

BiG*_*YaN 20

在C中这应该工作:

a = a^b;
b = a^b;
a = a^b;
Run Code Online (Sandbox Code Playgroud)

或者看起来更冷静/更好看:

a^=b;
b^=a;
a^=b;
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请查看此内容.XOR是一个非常强大的操作,有许多有趣的用法在这里和那里出现.

  • 为了使它更具可读性,你可以使用逗号运算符:a ^ = b,b ^ = a,a ^ = b; (2认同)

Mar*_*ork 19

为什么不使用std libs?

std::swap(a,b);
Run Code Online (Sandbox Code Playgroud)

  • @sandeepan:我或你不能解释问题所在.我们应该用问题的最佳解决方案回答所述的问题(如果不是OP要求那么我们将不会得到一个复选标记).但我认为这是被问到的问题的最佳解决方案(即使OP实际上正在玩愚蠢的采访类型问题). (6认同)
  • @Martin我不同意,我们应该在回答之前解释和理解,并继续思考我们是否正确解释.这个问题不是关于优化/最佳解决方案,而是关于不同的解决方案. (6认同)
  • 我认为提问者想要一个涉及较低级别细节的解决方案,而不仅仅是调用现成的函数/库. (3认同)
  • @sandeeoan:问题是我确实理解了他想要的问题.但是我"给了他他不需要的东西",因此他应该成为一个更好的开发者. (3认同)
  • @Martin在您的回复中没有迹象表明这是C ++特定的。例如,XOR交换可在任何地方使用。但是在C标准库中没有等效的c ++交换。 (3认同)

Mat*_*ery 15

在不使用任何临时存储或算术运算的情况下交换两个数字的最佳方法是将两个变量加载到寄存器中,然后以相反的方式使用寄存器!

你不能直接从C那样做,但是编译器可能很有能力为你解决(至少,如果启用了优化) - 如果你编写简单明了的代码,比如KennyTM在他的评论中建议的代码.

例如

void swap_tmp(unsigned int *p)
{
  unsigned int tmp;

  tmp = p[0];
  p[0] = p[1];
  p[1] = tmp;
}
Run Code Online (Sandbox Code Playgroud)

使用gcc 4.3.2编译并使用-O2优化标志给出:

swap_tmp:
        pushl   %ebp               ;  (prologue)
        movl    %esp, %ebp         ;  (prologue)
        movl    8(%ebp), %eax      ; EAX = p
        movl    (%eax), %ecx       ; ECX = p[0]
        movl    4(%eax), %edx      ; EDX = p[1]
        movl    %ecx, 4(%eax)      ; p[1] = ECX
        movl    %edx, (%eax)       ; p[0] = EDX
        popl    %ebp               ;  (epilogue)
        ret                        ;  (epilogue)
Run Code Online (Sandbox Code Playgroud)

  • 我不认为变量必须驻留在堆栈上才能被视为临时变量。 (2认同)

Tho*_*thy 6

我之前没有见过这个C解决方案,但我确信有人已经想到了它.并且可能比我更多地发布自我控制权.

fprintf(fopen("temp.txt", "w"), "%d", a);
a = b;
fscanf(fopen("temp.txt", "r"), "%d", &b);
Run Code Online (Sandbox Code Playgroud)

没有额外的变数!

它适用于我,但根据stdio实现,您可能需要做一些关于输出缓冲的事情.

  • 写入文件后不关闭文件并不适用于所有系统。而且太过分了! (3认同)

Shu*_* A. 6

使用XOR,

void swap(int &a, int &b)
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}
Run Code Online (Sandbox Code Playgroud)

一个带有XOR的衬里

void swap(int &a, int &b)
{
    a ^= b ^= a ^= b;
}
Run Code Online (Sandbox Code Playgroud)

这些方法看起来很干净,因为它们不会在任何测试用例中失败,但是又一次,因为(在方法2中)变量的值在同一序列点内被修改了两次,因此据说它具有由声明的未定义行为ANSIC。