就地交換兩個數是比較經典而且基礎的演算法之一。 我們要交換兩個數字,通常的做法就建立乙個中間變數,然後進行迴圈賦值,比如說下面的**:
void switch(int* p1, int* p2)
這種做法是最常見的一種交換兩個數字的方法,但研究演算法的人總是會提出比較詭異的問題,比如說在手持裝置中,記憶體資源很寶貴,要求不開闢新的空間,就地完成交換工作。
我們來考慮一下,如果想要就地完成這個交換的工作,從哲學地角度思考這個問題,我們手頭有兩個變數,要儲存兩個的資訊。我們將每個資訊儲存到乙個單獨的變數中,這是一種儲存方式,但如果使用這種儲存方式,我們是不可能完成就地交換的。那麼我們需要考慮另外一種儲存方式,用乙個變數儲存兩個資訊的集合,用另外乙個變數儲存任意乙個資訊,這種儲存方式就可以完成交換的工作。
上面這段話很抽象,我們用為**來表示
// 現在有兩個變數a, b,我使得
a = [a,b] // a 等於ab兩個資訊的集合
b = b // b 還是 b
這種表示方法,我們儲存了兩個資訊,但儲存方式不一樣,我們需要對資訊進行提取,例如我們要a時,則
c = a 去除 b
如果還是不明白這種儲存方式,那麼我直接給出就地交換的演算法:
void switch(int* p1, int* p2)
上面的**看起來有點煩? 把指標去掉看吧:
int a = 1;
int b = 2;
a = a + b;
b = a - b;
a = a - b;
這個思路很巧妙,但也存在一定問題: 萬一溢位了怎麼辦?
到目前為止,我們的答題思路是沒錯的,就是尋找另外一種資料儲存的模式,用乙個變數儲存兩條資訊的集合,我們仍然需要採用這種模式解決這個問題,但原先的簡單相加的模式是不行了,於是我們想到,集合兩個整型數字,是否可以從其二進位制表達方面來考慮?
我們可以使用位異或來儲存集合資訊。 用 1 和 0 來做簡單的驗證,看是否可以用異或的方式,儲存資訊的集合:
如果兩個數是a = 1和b = 0,則:
集合 = 1
0 異或 集合 = 1
1 異或 集合 = 0
如果 a = 1 & b = 1
集合 = 0
1 異或 集合 = 1
如果 a = 0 & b = 0
集合 = 0
0 疑惑 集合 = 0
驗證結果: 可以採用資訊集合的方式儲存
那麼我們的交換**可以變成:
int a = 10;
int b = 50;
a = a ^ b; // 構建集合
b = a ^ b; // 取出集合的另乙個元素
a = a ^ b; // 取出集合的另乙個元素
這種方式不用擔心資料溢位,應該算是就地交換兩個數的最佳解決方案了。
我在這篇文章裡提到的兩個數資訊的集合,這個概念應該不是很準確,只是我演算法功底有限,無法用比較精確的語言來表述我的想法,我覺得把這一類思想歸為使用資訊冗餘來進行資料備份比較合適。
我記得在幾年前,我的好朋友,國際非著名算法學家,國際著名大學博士後,2023年圖靈獎獲得者老盧先生就跟我聊過他的乙個關於伺服器上資料備份的想法。
他說,伺服器上的資料很重要,如果硬碟損壞,會造成難以估量的損失,所以需要對硬碟資料進行備份,但如果我們對每一塊硬碟都提供等價大小的空間進行備份的話,我們就需要兩倍數量的硬碟以保證備份的完整,這種冗餘是 100%。我們使用了100塊硬碟就必須再拿出100塊硬碟進行備份。但如果我們能夠將100塊硬碟上所有的資料異或一次,然後用一塊硬碟儲存起來,我們就可以使用一塊硬碟對100塊硬碟進行備份。
當然,具體將多少塊硬碟的資料集合在一起,是需要進行概率計算的,因為如果有兩塊硬碟同時損壞,那麼備份的資料就會失效。我們必須計算出多少塊硬碟裡,兩塊硬碟同時損壞的概率,小於使用100%冗餘方法備份中,執行硬碟和備份硬碟同時損壞的概率。在計算出這個數量以後,我們即可使用這種備份的方式。
不用臨時變數交換兩個數的值
就地交換兩個數是比較經典而且基礎的演算法之一。我們要交換兩個數字,通常的做法就建立乙個中間變數,然後進行迴圈賦值,比如說下面的 void switch int p1,int p2 這種做法是最常見的一種交換兩個數字的方法,但研究演算法的人總是會提出比較詭異的問題,比如說在手持裝置中,記憶體資源很寶貴...
不用臨時變數,交換兩個變數的值
在學習c語言的時候,涉及到兩個變數值的交換,其中用到臨時變數。類似於 temp a a b b temp 這樣的語句,如果在沒有臨時變數的情況下,該如何做呢?網路上的人們給出了兩種方法 一 異或法 a a b b b a a a b 二 加減法 a a b b a b a a b 其實我們看加減法更...
不用中間變數交換兩個數的值
當要交換兩個數的值時,通常的做法是定義乙個臨時變數,然後再進行交換。那麼能不能不用臨時變數而交換兩個數的值呢?可以的!c語言提供的異或運算就可以實現這樣的操作。異或運算子 也稱xor運算子,它的規則是若參加運算的兩個二進位同號,則結果為0 假 異號為1 真 即0 0 0,0 1 1,1 0 1,1 ...