交換兩個變數的思考

2022-03-18 17:48:22 字數 3069 閱讀 8822

網上存在三種方法:

1) 算術運算

簡單來說,就是通過+和-運算來實現。**如下:

int

a,b;

a=10;b=12

;a=b-a; //

a=2;b=12

b=b-a; //

a=2;b=10

a=b+a; //

a=12;b=10

通過以上運算,a和b中的值就進行了交換。表面上看起來很簡單,但是不容易想到,尤其是在習慣標準演算法之後。

此演算法與標準演算法相比,多了三個計算的過程,但是沒有借助臨時變數。(以下稱為算術演算法)

對於字串做這種交換的話, 可以使用字串連線和substr的方式來做, 建議在追加字串的時候, insert到那個字串的最前面, 防止其中乙個字串是另乙個字串的子串導致錯誤..

2) 指標操作

對指標的操作實際上進行的是整數運算。比如:兩個int指標相減得到乙個整數n,該整數表示兩個指標變數在記憶體中的儲存位置隔了n*sizeof(int)個位元組;int指標和乙個整數相加,例如「a+10」表示以a為基位址,偏移為10*sizeof(int)處的int變數。所以我們完全可以通過和算術演算法類似的運算來完成指標變數值的交換,從而達到交換變數的目的。即:

int *a,*b;    

a=new

int(10); //

給指標賦值

b=new

int(20); //

a=0x00030828,b=0x00030840

a=(int*)(b-a); //

a=0x00000006

b=(int*)(b-int(a)); //

b=0x00030828

a=(int*)(b+int(a)); //

a=0x00030840

需要注意的是:最後三句話中,只有第一句是兩個指標之間的計算,其他都是指標和整數的計算,否則會導致計算錯誤,嚴重導致系統出錯。

通過以上運算a、b的位址就完成了交換,a指向了原先b指向的值,b指向原先a指向的值!

此演算法同樣沒有使用第三變數就完成了值的交換,與算術演算法比較它顯得不好理解,但是它有它的優點即在交換很大的資料型別時,比如說自定義的大型結構或者類,它的執行速度比算術演算法快。因為它交換的時位址,而變數值在記憶體中是沒有移動過的。(以下稱為位址演算法)

3) 位運算

通過異或運算也能實現變數的交換,這也許是最為神奇的,請看以下**:

int a=10,b=12;  //

a=1010 b=1100;

a=a^b; //

a=1010^1100=0110;

b=a^b; //

b=0110^1100=1010;

a=a^b; //a=0110^1010=1100;

//a=1100=12;b=1010;

異或操作, 對每一位而言, 0可以取得原數, 1可以取得該位的補碼.   //異或----相同取0,不同取1

第一次異或, 用0填充了相同的位, 用1填充了不同的位.

第二次異或, 運算元b和第一次結果做異或, 第一次的結果用0(那些相同的位)取得了b自己的值(由於這些位相同), 而第一次結果是1的那些位, 則取得了運算元b的該位的補碼, 這些位的值是不同的, 因此, 運算元b中該位的補碼, 實際上就是運算元a中的原碼.

這樣, 第二次的異或中, 將第乙個運算元a中的所有位就都覆蓋到了運算元b中, 完成了將a賦值給b控制代碼的工作.

第三次異或, 原理和第二次一樣, 將b賦值給a控制代碼.

如果仔細思考,可以發現實際上有無數種方法。為什麼需要第三個變數?我想這是絕大多數初學程式設計時都思考過的問題。我本身是做訊號的,所以從資訊的角度來分析。兩個變數,必然存在兩份資訊(姑且以份為單位),如果直接交換,a=b,則a原來的資訊丟失,所以引入乙個臨時變數來儲存a的資訊,以確保資訊完整性。也就是說,temp的作用就是儲存交換過程可能損失的資訊量,那麼只要這個資訊量不損失,則無需temp.做編譯碼的人都知道,編碼的是殘差資料。殘差資料報含的就是那額外的資訊量。那麼,完全可以在交換過程中傳遞額外資訊,也就是a,b之間的耦合資訊,則交換過程不會發生資訊丟失,也就無需第三個變數。這耦合資訊可以是a-b,也可以是a^b,還可以是a*b.如:
a=a*b;
a=a/b;
b=a/b;
同樣可以完成交換(僅提供思路,未考慮除0溢位等問題)。舉一反三,可以有無窮種方法,但原理都是一樣的。

附上練習題目:

//

題目描述

////

請實現乙個演算法,在不使用額外資料結構和儲存空間的情況下,翻轉乙個給定的字串(可以使用單個過程變數)。

//給定乙個string inistring,請返回乙個string,為翻轉後的字串。保證字串的長度小於等於5000。

//測試樣例:

//"this is nowcoder"

//返回:"redocwon si siht"

#include

#include

using

namespace

std;

class

reverse

//for (int i = inistring.size(); i >0; i--)

//error: control reaches end of non-void function [-werror,-wreturn-type]

//沒有返回值啊

//

//兩個數字交換,可以借助第三變數,也可以不借助第三變數;有三種方法,自行總結

//inistring[i] ^= inistring[j] ^= inistring[i] ^= inistring[j];

//交換

for (int i = 0; i < inistring.size()/2; i++)

return

inistring;

}};

使用異或實現兩個數的交換

交換兩個變數

目的 實現兩個變數值的交換 以int 型別為例 方法一 使用臨時變數。優點 安全,適合任何型別資料交換,無溢位風險。缺點 保守 效率不高,需要使用第三方臨時變數 棧空間 1 void swap value int var1,int var2 2 方法二 利用 算術運算實現。優點 不需要額外的臨時變數...

swap交換兩個變數

最簡單的交換兩個變數值是用指標。void swap int a,int b work 這裡有個問題,一定要想清楚。為什麼在函式體內不能交換指標了?變成這樣 void swap int a,int b will not work在swap函式裡,a and b 都會產生乙個copy來,那你tmp a ...

交換兩個變數方法

將兩個變數的值互換,相當簡單的問題。假設有變數a b int a int b 方法1 將a b的值互換,為 int tmp a a b b tmp 然而,如果要求不用中間變數,就交換變數的值,該怎麼做呢?乙個比較有效率且眾所周知的方法就是 方法2 三次異或操作 int a 10,b 12 a 101...