Menukar dua nilai variabel tanpa menggunakan variabel ketiga


104

Salah satu pertanyaan yang sangat rumit ditanyakan dalam sebuah wawancara.

Tukar nilai dari dua variabel seperti a=10dan b=15.

Umumnya untuk menukar dua nilai variabel, kita membutuhkan variabel ke-3 seperti:

temp=a;
a=b;
b=temp;

Sekarang persyaratannya adalah, tukar nilai dua variabel tanpa menggunakan variabel ke-3.


76
Wow. Sebuah pertanyaan wawancara yang dipilih dengan buruk IMHO. Ini adalah teknik yang jarang berguna dalam praktiknya. Ada kemungkinan besar hal itu hanya akan membingungkan pengoptimal kompiler sehingga menghasilkan kode yang kurang efisien daripada "pertukaran sementara". Kecuali jika tempat ini Anda wawancarai terlibat dalam hal-hal yang sangat berat matematika (pikirkan: pengembangan algoritma enkripsi atau sejenisnya), saya tidak dapat membayangkan alasan bagus untuk mengajukan pertanyaan seperti itu.
Dan Moulding

10
Memang, pertanyaan itu tidak memberi tahu Anda apa pun selain apakah kandidat mengetahui trik khusus ini yang sangat tidak berguna dalam kode produksi. Saya kira Anda mungkin bertemu dengan penyihir sesekali yang mengetahuinya dengan cepat, tetapi orang-orang seperti itu yang belum tahu triknya kemungkinan besar sangat jarang.
CEO

2
Mungkin-mungkin mereka ingin menyingkirkan orang-orang yang mengira mengetahui trik semacam itu adalah apa yang membuat programmer yang baik? Juga, ketika membaca tentang xor-trick, perhatikan kapan itu akan gagal (yang IMO membuatnya sangat tidak berguna untuk pertukaran integer tujuan umum).
UncleBens

Jawaban:


155

Menggunakan algoritma xor swap

void xorSwap (int* x, int* y) {
    if (x != y) { //ensure that memory locations are different
       *x ^= *y;
       *y ^= *x;
       *x ^= *y;
    }
}


Kenapa di tes?

Tes ini untuk memastikan bahwa x dan y memiliki lokasi memori yang berbeda (bukan nilai yang berbeda). Ini karena (p xor p) = 0dan jika x dan y berbagi lokasi memori yang sama, ketika satu disetel ke 0, keduanya disetel ke 0. Jika * x dan * y sama-sama 0, semua operasi xor lainnya pada * x dan * y akan sama 0 (karena keduanya sama), yang berarti bahwa fungsi tersebut akan menyetel * x dan * y ke 0.

Jika mereka memiliki nilai yang sama tetapi tidak lokasi memori yang sama, semuanya bekerja seperti yang diharapkan

*x = 0011
*y = 0011
//Note, x and y do not share an address. x != y

*x = *x xor *y  //*x = 0011 xor 0011
//So *x is 0000

*y = *x xor *y  //*y = 0000 xor 0011
//So *y is 0011

*x = *x xor *y  //*x = 0000 xor 0011
//So *x is 0011


Haruskah ini digunakan?

Dalam kasus umum, tidak. Compiler akan mengoptimalkan variabel sementara dan mengingat bahwa swapping adalah prosedur umum, ia harus mengeluarkan kode mesin yang optimal untuk platform Anda.

Ambil contoh program tes cepat yang ditulis dalam C.

#include <stdlib.h>
#include <math.h>

#define USE_XOR 

void xorSwap(int* x, int *y){
    if ( x != y ){
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
    }
}

void tempSwap(int* x, int* y){
    int t;
    t = *y;
    *y = *x;
    *x = t;
}


int main(int argc, char* argv[]){
    int x = 4;
    int y = 5;
    int z = pow(2,28); 
    while ( z-- ){
#       ifdef USE_XOR
            xorSwap(&x,&y);
#       else
            tempSwap(&x, &y);
#       endif
    }
    return x + y;    
}

Disusun menggunakan:

gcc -Os main.c -o swap

Versi xor membutuhkan

real    0m2.068s
user    0m2.048s
sys  0m0.000s

Sedangkan versi dengan variabel sementara membutuhkan:

real    0m0.543s
user    0m0.540s
sys  0m0.000s

1
Mungkin ada baiknya menjelaskan mengapa pengujian (yaitu bahwa pendekatan xor rangkap tiga gagal secara mengerikan jika x dan y mereferensikan objek yang sama).
dmckee --- kucing mantan moderator

1
Saya tidak tahu bagaimana ini mendapat begitu banyak suara positif ketika kodenya rusak. Kedua swap di segmen kode yang diuji sepenuhnya salah. Lihat dekat.
SoapBox

@SoapBox: Poin yang sangat bagus! XOR swap nol x & meninggalkan y tidak tersentuh, dan temp swap meninggalkan keduanya dengan nilai x. Ups!
Drew Hall

4
@ SoapBox Tangkapan bagus. Diperbaiki dan diuji ulang dan saya tidak mendapatkan perbedaan besar dalam pengaturan waktu.
Yacoby

4
Penanya mengatakan dua variabel, bukan int. : P
Plumenator

93

bentuk umumnya adalah:

A = A operation B
B = A inverse-operation B
A = A inverse-operation B 

namun Anda harus berhati-hati terhadap luapan dan juga tidak semua operasi memiliki invers yang didefinisikan dengan baik untuk semua nilai yang ditentukan oleh operasi. misal * dan / bekerja sampai A atau B bernilai 0

xor sangat menyenangkan karena didefinisikan untuk semua int dan merupakan kebalikannya sendiri


XOR (X, X) == 0, jadi xor bekerja untuk int KECUALI ketika dua nilai yang ditukar sama. Saya bukan orang pertama yang menunjukkan hal ini dan terlalu banyak yang mengatakannya (di sini dan di tempat lain) untuk memilih siapa pun untuk mendapatkan pujian.
AlanK

85
a = a + b
b = a - b // b = a
a = a - b

16
Bagaimana jika a+bmeluap?
Alok Singhal

2
@Alok: Itu tidak dipertimbangkan, jadi tidak praktis :)
Dor

4
Jika a dan b memiliki tipe bilangan bulat yang sama, dasar, berukuran (seperti int,, unsigned short...), ini tetap berhasil pada akhirnya, bahkan dengan melimpah, karena jika a + b meluap, maka a - b akan meluap. Dengan tipe bilangan bulat dasar ini, nilainya hanya berputar-putar.
Patrick Johnmeyer

10
Di C, menggunakan ini pada unsignedtipe integer OK dan selalu berfungsi. Pada tipe bertanda tangan, ini akan memunculkan perilaku tidak terdefinisi pada overflow.
jpalecek

1
@Shahbaz: Meskipun bilangan bulat bertanda tangan disimpan dalam pelengkap 2, perilaku overflow masih belum ditentukan.
Keith Thompson

79

Belum ada yang menyarankan penggunaan std::swap.

std::swap(a, b);

Saya tidak menggunakan variabel sementara dan tergantung pada jenis adan bimplementasinya mungkin memiliki spekulasi yang tidak baik. Implementasinya harus ditulis dengan mengetahui apakah 'trik' itu sesuai atau tidak. Tidak ada gunanya mencoba menebak-nebak.

Secara lebih umum, saya mungkin ingin melakukan sesuatu seperti ini, karena ini akan bekerja untuk jenis kelas yang memungkinkan ADL untuk menemukan kelebihan beban yang lebih baik jika memungkinkan.

using std::swap;
swap(a, b);

Tentu saja, reaksi pewawancara terhadap jawaban ini mungkin banyak menjelaskan tentang lowongan tersebut.


tentunya di C ++ 0x swap akan menggunakan referensi rvalue jadi akan lebih baik lagi!
jk.

16
Semua orang ingin memamerkan xor mengkilap atau trik lain yang mereka pelajari, dengan berbagai peringatan tentang cara menggunakannya, tetapi ini pasti jawaban terbaik.

2
kenapa tidak std :: swap (a, b); ? Maksud saya mengapa menggunakan?
Dinaiz

2
@Dinaiz tanpa implementasi yang std::ditentukan swappengguna untuk jenis yang ditentukan pengguna juga tersedia untuk dipanggil (inilah yang dimaksud dengan "ini akan berfungsi untuk jenis kelas yang memungkinkan ADL untuk menemukan kelebihan beban yang lebih baik jika memungkinkan").
Kyle Strand

std::swapmenggunakan memori sementara tambahan dalam implementasinya, bukan? cplusplus.com/reference/utility/swap
Ninja

19

Seperti yang telah dicatat oleh manu, algoritma XOR adalah salah satu yang populer yang bekerja untuk semua nilai integer (termasuk pointer, dengan sedikit keberuntungan dan casting). Demi kelengkapan saya ingin menyebutkan algoritma lain yang kurang kuat dengan penambahan / pengurangan:

A = A + B
B = A - B
A = A - B

Di sini Anda harus berhati-hati terhadap overflows / underflows, tetapi selain itu berfungsi dengan baik. Anda bahkan dapat mencoba ini pada pelampung / ganda jika XOR tidak diizinkan pada mereka.


" semua nilai integer (itu termasuk pointer) " - Apa? Tidak, pointer bukan bilangan bulat, dan Anda tidak bisa xor nilai pointer. Anda juga tidak bisa xor nilai floating-point. Tetapi metode penambahan / pengurangan memiliki perilaku yang tidak ditentukan (untuk tipe bertanda tangan atau floating-point) pada overflow atau underflow, dapat kehilangan presisi untuk floating-point, dan tidak dapat diterapkan ke pointer atau tipe non-numerik lainnya.
Keith Thompson

@KeithThompson - Oke, hilangnya presisi untuk floating point memang benar, tetapi tergantung pada situasinya, hal itu dapat diterima. Adapun petunjuknya - yah, saya belum pernah mendengar tentang kompiler / platform di mana pointer tidak dapat dengan bebas dilemparkan ke bilangan bulat dan kembali lagi (berhati-hatilah untuk memilih bilangan bulat dengan ukuran yang tepat, tentu saja). Tapi kemudian, saya bukan ahli C / C ++. Saya tahu ini bertentangan dengan standar, tetapi saya mendapat kesan bahwa perilaku ini cukup konsisten di ... semuanya.
Vilx-

1
@ Vilx-: Mengapa kehilangan presisi dapat diterima jika sangat mudah untuk menghindarinya dengan menggunakan variabel sementara - atau std::swap()? Tentu, Anda dapat mengonversi pointer ke integer dan kembali lagi (dengan asumsi ada tipe integer yang cukup besar, yang tidak dijamin), tapi bukan itu yang Anda sarankan; Anda menyiratkan bahwa pointer adalah bilangan bulat, bukan bahwa mereka dapat diubah menjadi bilangan bulat. Ya, jawaban yang diterima tidak akan berfungsi untuk petunjuk. Jawaban Charles Bailey menggunakan std::swapbenar-benar satu-satunya yang benar.
Keith Thompson

1
Pertama-tama, pertanyaannya adalah "bagaimana menukar tanpa menggunakan variabel ketiga" dan alasan yang diberikan untuk itu adalah "pertanyaan wawancara". Saya hanya memberikan satu kemungkinan jawaban lain. Kedua, OK, permintaan maaf saya karena menyiratkan bahwa petunjuk adalah bilangan bulat. Saya memperbarui jawaban agar lebih eksplisit dan benar. Harap perbaiki saya jika saya masih salah (atau perbarui sendiri jawabannya). Ketiga, saya menghapus bagian tentang jawaban yang diterima. Ini tidak menggunakan cast pointer-ke-integer di mana pun dan berfungsi dengan benar (sejauh yang saya mengerti).
Vilx-

@KeithThompson: Pertanyaannya bisa diubah menjadi tentang bagaimana std::swapdapat diimplementasikan tanpa menggunakan variabel ketiga.
jxh

10

Pertanyaan bodoh pantas mendapatkan jawaban yang tepat:

void sw2ap(int& a, int& b) {
  register int temp = a; // !
  a = b;
  b = temp;
}

Satu-satunya penggunaan registerkata kunci yang baik.


1
Apakah sebuah objek dideklarasikan dengan register kelas penyimpanan bukan "variabel"? Juga saya tidak yakin ini adalah penggunaan register yang baik, karena jika kompiler Anda tidak dapat mengoptimalkan ini, apa gunanya mencoba, Anda harus menerima sampah apa pun yang Anda dapatkan atau menulis rakitan sendiri ;-) Tetapi sebagai Anda berkata, pertanyaan yang cerdik pantas mendapatkan jawaban yang cerdik.
Steve Jessop

1
Hampir semua kompiler modern mengabaikan kelas penyimpanan register, karena mereka memiliki gagasan yang jauh lebih baik tentang apa yang sering diakses daripada Anda.
CEO

6
Perhatikan bahwa jawaban ini ditujukan untuk wawancara (er), bukan penyusun. Ini terutama mengambil keuntungan dari kenyataan bahwa jenis pewawancara yang menanyakan pertanyaan semacam ini tidak benar-benar memahami C ++. Jadi, mereka tidak bisa menolak jawaban ini. (dan tidak ada jawaban Standar; ISO C ++ berbicara tentang objek, bukan variabel).
MSalters

Ah, aku mengerti. Saya mencari di standar C untuk menyebutkan variabel sebagai kata benda, dan tidak hanya berarti non-const. Saya menemukan satu di n1124, di bagian untuk loop yang mendefinisikan ruang lingkup "variabel" yang dideklarasikan di inisialisasi. Kemudian saya menyadari pertanyaannya adalah C ++, dan tidak repot-repot mencari untuk melihat apakah C ++ telah membuat kesalahan ketik yang sama di mana saja.
Steve Jessop

3

Menukar dua angka menggunakan variabel ketiga menjadi seperti ini,

int temp;
int a=10;
int b=20;
temp = a;
a = b;
b = temp;
printf ("Value of a", %a);
printf ("Value of b", %b);

Menukar dua angka tanpa menggunakan variabel ketiga

int a = 10;
int b = 20;
a = a+b;
b = a-b;
a = a-b;
printf ("value of a=", %a);
printf ("value of b=", %b);

2
#include<iostream.h>
#include<conio.h>
void main()
{
int a,b;
clrscr();
cout<<"\n==========Vikas==========";
cout<<"\n\nEnter the two no=:";
cin>>a>>b;
cout<<"\na"<<a<<"\nb"<<b;
a=a+b;
b=a-b;
a=a-b;

cout<<"\n\na="<<a<<"\nb="<<b;
getch();
}

1
Setelah cout << "Enter the two no=:"saya mengharapkan untuk membacacout << "Now enter the two no in reverse order:"
user253751

Seperti beberapa jawaban lainnya, ini memiliki perilaku tidak terdefinisi jika a+batau a-bmeluap. Juga, void main()tidak valid dan <conio.h>tidak standar.
Keith Thompson

2

Karena solusi aslinya adalah:

temp = x; y = x; x = temp;

Anda dapat membuatnya menjadi dua liner dengan menggunakan:

temp = x; y = y + temp -(x=y);

Kemudian buat satu liner dengan menggunakan:

x = x + y -(y=x);

1
Perilaku tidak terdefinisi. ydibaca dan ditulis dalam ekspresi yang sama tanpa titik urutan yang mengintervensi.
Keith Thompson

1

Jika Anda mengubah sedikit pertanyaan untuk menanyakan tentang 2 register perakitan sebagai ganti variabel, Anda juga dapat menggunakan xchgoperasi sebagai satu opsi, dan operasi tumpukan sebagai yang lain.


1
xchgOperasi apa yang Anda maksud? Pertanyaannya tidak menentukan arsitektur CPU.
Keith Thompson

1

Pertimbangkan a=10, b=15:

Menggunakan Penjumlahan dan Pengurangan

a = a + b //a=25
b = a - b //b=10
a = a - b //a=15

Menggunakan Pembagian dan perkalian

a = a * b //a=150
b = a / b //b=10
a = a / b //a=15

1
Memiliki perilaku tidak terdefinisi saat melimpah.
Keith Thompson

1
Selain itu, di C ++, ini mungkin memiliki perilaku yang tidak diinginkan jika nilainya bukan tipe yang sama. Misalnya, a=10dan b=1.5.
Matthew Cole

1
#include <iostream>
using namespace std;
int main(void)
{   
 int a,b;
 cout<<"Enter a integer" <<endl;
 cin>>a;
 cout<<"\n Enter b integer"<<endl;
 cin>>b;

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

  cout<<" a= "<<a <<"   b="<<b<<endl;
  return 0;
}

Pembaruan: Dalam hal ini kami mengambil masukan dari dua bilangan bulat dari pengguna. Kemudian kami menggunakan operasi XOR bitwise untuk menukarnya.

Katakanlah kita memiliki dua bilangan bulat a=4dan b=9kemudian:

a=a^b --> 13=4^9 
b=a^b --> 4=13^9 
a=a^b --> 9=13^9

Tolong tambahkan penjelasan singkat pada jawaban Anda untuk pengunjung selanjutnya.
Nikolay Mihaylov

1
Dalam hal ini kami mengambil masukan dari dua bilangan bulat dari pengguna. Kemudian kami menggunakan operasi bitwise xor dua menukar mereka. Katakanlah kita memiliki dua interger a = 4 dan b = 9 maka sekarang a = a ^ b -> 13 = 4 ^ 9 b = a ^ b -> 4 = 13 ^ 9 a = a ^ b -> 9 = 13 ^ 9
Naeem Ul Hassan

1

Berikut satu solusi lagi tetapi satu risiko.

kode:

#include <iostream>
#include <conio.h>
void main()
{

int a =10 , b =45;
*(&a+1 ) = a;
a =b;
b =*(&a +1);
}

nilai apa pun di lokasi a + 1 akan diganti.


2
Itu adalah jawaban yang berguna, mungkin nilainya lenyap.
Bibi Tahira

1
Beberapa jenis perilaku tidak terdefinisi. *(&a+1)mungkin saja b. void main()tidak valid. <conio.h>tidak standar (dan Anda bahkan tidak menggunakannya).
Keith Thompson

Kode tersebut diuji dengan parameter keluaran lain, yang dikecualikan, karena saya telah menyebutkan risiko. Risiko memori diganti .. Itu ada .. Tapi itu berguna untuk menukar dua variabel tanpa keterlibatan ketiga.
DareDevil

Bagian terburuknya adalah ini mungkin benar-benar berfungsi beberapa kali, jadi Anda mungkin tidak segera menyadarinya benar-benar rusak dan akan gagal dalam pengoptimalan, kompiler lain, dll.
avl_sweden

1

Tentu saja, jawaban C ++ seharusnya std::swap .

Namun, juga tidak ada variabel ketiga dalam implementasi berikut ini swap:

template <typename T>
void swap (T &a, T &b) {
    std::pair<T &, T &>(a, b) = std::make_pair(b, a);
}

Atau, sebagai satu baris:

std::make_pair(std::ref(a), std::ref(b)) = std::make_pair(b, a);

0
#include <stdio.h>

int main()
{
    int a, b;
    printf("Enter A :");
    scanf("%d",&a);
    printf("Enter B :");
    scanf("%d",&b);
    a ^= b;
    b ^= a;
    a ^= b;
    printf("\nValue of A=%d B=%d ",a,b);
    return 1;
}

0

itulah algoritma swap XOR yang benar

void xorSwap (int* x, int* y) {
   if (x != y) { //ensure that memory locations are different
      if (*x != *y) { //ensure that values are different
         *x ^= *y;
         *y ^= *x;
         *x ^= *y;
      }
   }
}

Anda harus memastikan bahwa lokasi memori berbeda dan juga bahwa nilai sebenarnya berbeda karena A XOR A = 0


Anda tidak harus memastikan nilainya berbeda.
pengguna253751

0

Anda dapat melakukan .... dengan cara yang mudah ... dalam satu baris Logika

#include <stdio.h>

int main()
{
    int a, b;
    printf("Enter A :");
    scanf("%d",&a);
    printf("Enter B :");
    scanf("%d",&b);
    int a = 1,b = 2;
    a=a^b^(b=a);
    printf("\nValue of A=%d B=%d ",a,b);

    return 1;
}

atau

#include <stdio.h>

int main()
{
    int a, b;
    printf("Enter A :");
    scanf("%d",&a);
    printf("Enter B :");
    scanf("%d",&b);
    int a = 1,b = 2;
    a=a+b-(b=a);
    printf("\nValue of A=%d B=%d ",a,b);

    return 1;
}

1
Perilaku tidak terdefinisi. Di kedua versi, bkeduanya dibaca dan dimodifikasi dalam ekspresi yang sama, tanpa titik urutan yang mengganggu.
Keith Thompson

0
public void swapnumber(int a,int b){
    a = a+b-(b=a);
    System.out.println("a = "+a +" b= "+b);
}

0

Jawaban terbaik adalah menggunakan XOR dan menggunakannya dalam satu baris akan keren.

    (x ^= y), (y ^= x), (x ^= y);

x, y adalah variabel dan koma di antara keduanya memperkenalkan titik urutan sehingga tidak menjadi dependen compiler. Bersulang!


0

Mari kita lihat contoh c sederhana untuk menukar dua angka tanpa menggunakan variabel ketiga.

program 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();
}

Keluaran:

Sebelum pertukaran a = 10 b = 20 Setelah pertukaran a = 20 b = 10

Program 2: Menggunakan * dan /

Mari kita lihat contoh lain untuk menukar dua angka menggunakan * dan /.

#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();
}

Keluaran:

Sebelum pertukaran a = 10 b = 20 Setelah pertukaran a = 20 b = 10

Program 3: Memanfaatkan operator XOR bitwise:

Operator bitwise XOR dapat digunakan untuk menukar dua variabel. XOR dari dua bilangan x dan y mengembalikan bilangan yang memiliki semua bit sebagai 1 di mana bit x dan y berbeda. Misalnya, XOR dari 10 (Dalam Biner 1010) dan 5 (Dalam Biner 0101) adalah 1111 dan XOR dari 7 (0111) dan 5 (0101) adalah (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;

Keluaran:

Setelah Penukaran: x = 5, y = 10

Program 4:

Belum ada yang menyarankan menggunakan std :: swap.

std::swap(a, b);

Saya tidak menggunakan variabel sementara apa pun dan bergantung pada jenis a dan b, implementasinya mungkin memiliki spesialisasi yang juga tidak. Implementasinya harus ditulis dengan mengetahui apakah 'trik' itu sesuai atau tidak.

Masalah dengan metode di atas:

1) Pendekatan berbasis perkalian dan pembagian tidak akan berhasil jika salah satu bilangan adalah 0 karena hasil kali menjadi 0 terlepas dari bilangan lainnya.

2) Kedua solusi Aritmatika dapat menyebabkan luapan aritmatika. Jika x dan y terlalu besar, penjumlahan dan perkalian mungkin keluar dari kisaran bilangan bulat.

3) Saat kita menggunakan pointer ke variabel dan melakukan pertukaran fungsi, semua metode di atas gagal ketika kedua pointer menunjuk ke variabel yang sama. Mari kita lihat apa yang akan terjadi dalam kasus ini jika keduanya menunjuk ke variabel yang sama.

// Metode berbasis Bitwise XOR

x = x ^ x; // x becomes 0
x = x ^ x; // x remains 0
x = x ^ x; // x remains 0

// Metode berbasis aritmatika

x = x + x; // x becomes 2x
x = x  x; // x becomes 0
x = x  x; // x remains 0

Yuk kita simak programnya berikut ini.

#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;
}

Keluaran :

Setelah penukaran (& x, & x): x = 0

Menukar variabel dengan dirinya sendiri mungkin diperlukan di banyak algoritme standar. Misalnya, lihat implementasi QuickSort ini di mana kita dapat menukar variabel dengan dirinya sendiri. Masalah di atas dapat dihindari dengan menempatkan kondisi sebelum melakukan swapping.

#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;
}

Keluaran :

Setelah pertukaran (& x, & x): x = 10


0

Mungkin di luar topik, tetapi jika Anda tahu apa yang Anda tukar variabel tunggal antara dua nilai yang berbeda, Anda mungkin dapat melakukan logika array. Setiap kali baris kode ini dijalankan, itu akan menukar nilai antara 1 dan 2.

n = [2, 1][n - 1]

0

Anda bisa melakukan:

std::tie(x, y) = std::make_pair(y, x);

Atau gunakan make_tuple saat menukar lebih dari dua variabel:

std::tie(x, y, z) = std::make_tuple(y, z, x);

Tapi saya tidak yakin apakah secara internal std :: tie menggunakan variabel sementara atau tidak!


0

Dalam javascript:

function swapInPlace(obj) {
    obj.x ^= obj.y
    obj.y ^= obj.x
    obj.x ^= obj.y
}

function swap(obj) {
    let temp = obj.x
    obj.x = obj.y
    obj.y = temp
}

Perhatikan waktu eksekusi kedua opsi.

Dengan menjalankan kode ini saya mengukurnya.

console.time('swapInPlace')
swapInPlace({x:1, y:2})
console.timeEnd('swapInPlace') // swapInPlace: 0.056884765625ms

console.time('swap')
swap({x:3, y:6})
console.timeEnd('swap')        // swap: 0.01416015625ms

Seperti yang Anda lihat (dan seperti yang dikatakan banyak orang), swap di tempat (xor) membutuhkan banyak waktu daripada opsi lain menggunakan variabel temp.


0

R kehilangan penugasan bersamaan seperti yang diusulkan oleh Edsger W. Dijkstra dalam A Discipline of Programming , 1976, bag.4, p.29. Ini akan memungkinkan solusi yang elegan:

a, b    <- b, a         # swap
a, b, c <- c, a, b      # rotate right

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

Ini sangat sederhana, tetapi mungkin menimbulkan peringatan.


5
Peringatannya adalah bahwa itu tidak berhasil? Kami tidak tahu apakah b=adilakukan sebelum atau sesudah a + b.
Bo Persson

-1

solusi baris tunggal untuk menukar dua nilai dalam bahasa c.

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

Perilaku tidak terdefinisi saat melimpah.
Keith Thompson

-1
second_value -= first_value;
first_value +=  second_value;
second_value -= first_value;
second_value *= -1;

Ini memiliki perilaku tidak terdefinisi jika salah satu operasi meluap atau kurang. Itu juga bisa kehilangan presisi jika objeknya berupa floating-point.
Keith Thompson
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.