Подивимося простий приклад 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 Після swap 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 Після swap a = 20 b = 10
Програма 3: Використання побітового оператора XOR:
Бітовий оператор XOR може використовуватися для обміну двома змінними. XOR з двох чисел x і y повертає число, яке має всі біти як 1, де б біти x і y не відрізнялися. Наприклад, XOR 10 (In Binary 1010) і 5 (In Binary 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