1. 程式人生 > >不借助第三個變數交換兩個整數

不借助第三個變數交換兩個整數

假設兩個數x和y,則有:

方法1,算術運算(加減):

x=x+y; //x暫存兩數之和 y=x-y; //y為兩數之和減去y,即原來的x x=x-y; //x為兩數之和減去現在的y(原來的x),變成原來的y

方法2,邏輯運算(異或):

x^=y;//x先存x和y兩者的資訊 y^=x;//保持x不變,利用x異或反轉y的原始值使其等於x的原始值 x^=y;//保持y不變,利用x異或反轉y的原始值使其等於y的原始值

關於異或運算要牢記兩個原則:

任何一位二進位制數同 1 異或都會變成另外一個(0 同 1 異或的結果是 1,1 同 1 異或的結果是 0)
任何一位二進位制數同 0 異或都保持不變(0 同 0 異或的結果是 0,1 同 0 異或的結果是 1)

實現這個操作的方法很多。

最基本的方法就是使用一個臨時變數,具體的程式碼如下:

int a,b;
int tmp;
tmp=a;
a=b;
b=tmp; 另外,還經常出現的一種情況是不使用臨時變數來交換兩個整型數,一般常見的方法有兩種:加法和異或運算,具體如下表所示:
複製程式碼 void swap1(int& x,int& y)
{
x=x+y;
y=x-y;
x=x-y;
} 複製程式碼
複製程式碼 void swap2(int &x,int &y)
{
x=x-y;
y=x+y;
x=y-x;
} 複製程式碼
複製程式碼 void swap3(int& x,int& y)
{
x ^= y;
y ^= x;
x ^= y;
} 複製程式碼

x和y同號的情況下容易溢位

x和y異號的情況下容易溢位

左邊的兩種交換也存在問題就是整數的溢位。

所以更嚴謹的做法如下:

複製程式碼 void swap4(int &x,int &y)
{
if(x==y)
return ;
if((x>0&&y>0)||(x<0&&y<0)) {
x=x-y;
y=x+y;
x=y-x;
}
else{
x=x+y;
y=x-y;
x=x-y;
}
} 複製程式碼
複製程式碼 void swap5(int &x,int &y)
{
if(x==y)
return;
x^=y;
y^=x;
x^=y;
} 複製程式碼
複製程式碼 void swap7(int &x,int &y)
{
if(x==y)
return;
y=x+y-(x=y);
} 複製程式碼

【擴充套件】

另外,還有不使用臨時變數交換N個整型數的操作, 

有N(N>=2)個變數,不使用臨時變數,如何順次交換它們的值?能否只用一條語句實現?如 +---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
| 1 | 2 | 3 | 4 | 5 |
+---+---+---+---+---+ 要把它變為 +---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
| 2 | 3 | 4 | 5 | 1 |
+---+---+---+---+---+ 怎樣實現? 首先,我們考慮用異或實現兩個變數的交換,可參考我的這篇文章《不用臨時變數交換兩個數的值》。用C++寫函式如下:

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

    return b;
}

然後可以把程式碼優化為:

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

    return b;
}

繼續優化,把三句壓縮為一句,如下:

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

還可再優化,如下:

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

現在來順次交換5個變數的值,如下:

swap(a, b);        //返回b

swap(b, c);        //返回c

swap(c, d);        //返回d

swap(d, e);        

既然有返回值,那麼可以寫成鏈式的,如下:

swap(a, b);                                 //返回b

swap(swap(a, b), c);                        //返回c

swap(swap(swap(a, b), c), d);               //返回d

swap(swap(swap(swap(a, b), c), d), e);        

現在,讓我們來把swap函式依次用相應的函式體替換掉,如下:

e ^= d ^= e ^= swap(swap(swap(a, b), c), d);

e ^= d ^= e ^= d ^= c ^= d ^= swap(swap(a, b), c);

e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= swap(a, b);

e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= b ^= a ^= b ^= a;