Как поменять местами два числа без использования временных переменных или арифметических операций? - PullRequest
35 голосов
/ 05 сентября 2010

Это уравнение заменяет два числа без временной переменной, но использует арифметические операции:

a = (a+b) - (b=a);

Как я могу сделать это без арифметических операций?Я думал о XOR.

Ответы [ 12 ]

20 голосов
/ 23 августа 2011
a=a+b;
b=a-b;
a=a-b;

Это просто, но эффективно ....

20 голосов
/ 05 сентября 2010

В C это должно работать:

a = a^b;
b = a^b;
a = a^b;

ИЛИ кулер / гейкер с видом:

a^=b;
b^=a;
a^=b;

Для более подробной информации смотрите this .XOR - очень мощная операция, в которой есть много интересных способов использования.

19 голосов
/ 05 сентября 2010

Почему бы не использовать стандартные библиотеки?

std::swap(a,b);
15 голосов
/ 05 сентября 2010

Лучший способ поменять два числа без использования временного хранилища или арифметических операций - это загрузить обе переменные в регистры, а затем использовать регистры наоборот!

Вы не можете сделать это непосредственно из C, но компилятор, вероятно, вполне способен решить это за вас (по крайней мере, если оптимизация включена) - если вы пишете простой, очевидный код, такой как тот, который предложил KennyTM в своем комментарии.

, например

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

  tmp = p[0];
  p[0] = p[1];
  p[1] = tmp;
}

, скомпилированный с 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)
6 голосов
/ 08 февраля 2015

Используя XOR,

void swap(int &a, int &b)
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}

Один вкладыш с XOR,

void swap(int &a, int &b)
{
    a ^= b ^= a ^= b;
}

Эти методы кажутся чистыми, потому что они не терпят неудачу ни в одном тестовом примере, но опять же, поскольку (как в методе 2) значение переменной изменяется дважды в одной и той же точке последовательности, говорят, что она имеет неопределенное поведение, заявленное ANSI C.

6 голосов
/ 09 января 2015

Я не видел этого решения C раньше, но я уверен, что кто-то думал об этом. И, возможно, у меня было больше самоконтроля, чем у меня.

fprintf(fopen("temp.txt", "w"), "%d", a);
a = b;
fscanf(fopen("temp.txt", "r"), "%d", &b);

Никаких дополнительных переменных!

Это работает для меня, но в зависимости от реализации stdio вам, возможно, придется что-то делать с буферизацией вывода.

3 голосов
/ 07 ноября 2013

a = ((a = a + b) - (b = a - b));

1 голос
/ 29 июня 2019

C++11 позволяет:

0 голосов
/ 21 марта 2017

Простое решение, которое я помню из моих бакалавров: -)

a = a+b-(b=a);

Example

0 голосов
/ 20 августа 2015

Умножение и деление также могут быть использованы.

 int x = 10, y = 5;

 // Code to swap 'x' and 'y'
 x = x * y;  // x now becomes 50
 y = x / y;  // y becomes 10
 x = x / y;  // x becomes 5
...