Давайте посмотрим на простой пример c, чтобы поменять местами два числа без использования третьей переменной.
программа 1:
#include<stdio.h>
#include<conio.h>
main()
{
int a=10, b=20;
clrscr();
printf("Before swap a=%d b=%d",a,b);
a=a+b;//a=30 (10+20)
b=a-b;//b=10 (30-20)
a=a-b;//a=20 (30-10)
printf("\nAfter swap a=%d b=%d",a,b);
getch();
}
Вывод:
До свопа a = 10 b = 20 После свопа a = 20 b = 10
Программа 2: Использование * и /
Давайте посмотрим на другой пример, чтобы поменять местами два числа с помощью * и /.
#include<stdio.h>
#include<conio.h>
main()
{
int a=10, b=20;
clrscr();
printf("Before swap a=%d b=%d",a,b);
a=a*b;//a=200 (10*20)
b=a/b;//b=10 (200/20)
a=a/b;//a=20 (200/10)
printf("\nAfter swap a=%d b=%d",a,b);
getch();
}
Вывод:
До свопа a = 10 b = 20 После свопа a = 20 b = 10
Программа 3: Использование побитового оператора XOR:
Побитовый оператор XOR можно использовать для обмена двумя переменными. XOR двух чисел x и y возвращает число, в котором все биты равны 1, если биты x и y различаются. Например, XOR для 10 (в двоичном формате 1010) и 5 (в двоичном формате 0101) равно 1111, а XOR для 7 (0111) и 5 (0101) равно (0010).
#include <stdio.h>
int main()
{
int x = 10, y = 5;
// Code to swap 'x' (1010) and 'y' (0101)
x = x ^ y; // x now becomes 15 (1111)
y = x ^ y; // y becomes 10 (1010)
x = x ^ y; // x becomes 5 (0101)
printf("After Swapping: x = %d, y = %d", x, y);
return 0;
Вывод:
После обмена: x = 5, y = 10
Программа 4:
Пока никто не предлагал использовать std :: swap.
std::swap(a, b);
Я не использую какие-либо временные переменные, и в зависимости от типа a и b реализация может иметь специализацию, которой тоже нет. Реализация должна быть написана с учетом того, уместен ли «трюк».
Проблемы с вышеуказанными методами:
1) Подход, основанный на умножении и делении, не работает, если одно из чисел равно 0, поскольку произведение становится 0 независимо от другого числа.
2) Оба арифметических решения могут вызвать арифметическое переполнение. Если x и y слишком велики, сложение и умножение могут выйти за пределы целочисленного диапазона.
3) Когда мы используем указатели на переменную и выполняем замену функций, все вышеперечисленные методы не работают, когда оба указателя указывают на одну и ту же переменную. Давайте посмотрим, что произойдет в этом случае, если оба будут указывать на одну и ту же переменную.
// Побитовый метод на основе XOR
x = x ^ x; // x becomes 0
x = x ^ x; // x remains 0
x = x ^ x; // x remains 0
// Метод на основе арифметики
x = x + x; // x becomes 2x
x = x – x; // x becomes 0
x = x – x; // x remains 0
Посмотрим на следующую программу.
#include <stdio.h>
void swap(int *xp, int *yp)
{
*xp = *xp ^ *yp;
*yp = *xp ^ *yp;
*xp = *xp ^ *yp;
}
int main()
{
int x = 10;
swap(&x, &x);
printf("After swap(&x, &x): x = %d", x);
return 0;
}
Выход :
После обмена (& x, & x): x = 0
Замена переменной самой собой может потребоваться во многих стандартных алгоритмах. Например, посмотрите эту реализацию QuickSort, где мы можем поменять местами переменную с собой. Вышеупомянутой проблемы можно избежать, поставив условие перед заменой.
#include <stdio.h>
void swap(int *xp, int *yp)
{
if (xp == yp) // Check if the two addresses are same
return;
*xp = *xp + *yp;
*yp = *xp - *yp;
*xp = *xp - *yp;
}
int main()
{
int x = 10;
swap(&x, &x);
printf("After swap(&x, &x): x = %d", x);
return 0;
}
Выход :
После обмена (& x, & x): x = 10