在編程的一些算法中,交換函數雖然不起眼,但也是一個不可或缺的組成部分。少了它,很多算法就難以為繼。交換函數定義就是交換兩個變量的值。有一點編程基礎的人都能很快速的寫出代碼來。
Public Shared Sub SwapNumber(ByRef N1 As Integer, ByRef N2 As Integer)
Dim I As Integer
I=N1
N1=N2
N2=I
End Sub
這一段代碼只寫了Integer型的函數,其它類型的類似。
但是,這個函數效率不高,額外的利用一個中間變量I。
有人,利用Xor運算的回復性,寫了下面一段代碼來
Public Shared Sub SwapNumber(ByRef N1 As Integer, ByRef N2 As Integer)
N1 = N1 Xor N2
N2 = N1 Xor N2
N1 = N1 Xor N2
End Sub
測試一下這個函數
N=6
M=7
SwapNumber(N,M)
嗯,結果滿意。N和M的值的確交換了。
但是這個函數有一個陷阱,不注意的話,會產生一個嚴重的邏輯錯誤。
用下面的測試
N=6
SwapNumber(N,N)
從需要來看。N和N交換,N的值應該還是6
可是實際的結果令人瞠目,N=0。為何?
關鍵是ByRef這個關鍵字,他引用的是變量的地址。在調用SwapNumber(N,N)這個函數的時候,N1和N2都引用N這個變量。當N1或者N2值發生改變的時候,N1、N2、N這三個變量是一起變化的。那麼在第一行的時候,N1 = N1 Xor N2。實際執行的是N1=6 Xor 6=0,同時,N2的值也發生了變化,N2=0,因為N1和N2指向同一個變量。那後面就很好的理解了。最後退出函數的時候,N就是N1就是N2等於0
怎麼解決?在代碼中加一行,遇到值相等的時候,就直接退出函數。因為這個時候,換與不換是一樣的。
Public Shared Sub SwapNumber(ByRef N1 As Integer, ByRef N2 As Integer)
If N1 = N2 Then Exit Sub
N1 = N1 Xor N2
N2 = N1 Xor N2
N1 = N1 Xor N2
End Sub
在很多的書本與網頁上講到本算法的時候,都不會提到這個“陷阱”,那是因為在不同的編程語言中,這個陷阱是不一定出現的。我們看了一個算法,用自己的所熟悉的語言去實現它的時候,一定要做全方位的測試,要找到各個方面的陷阱,不要生搬硬套,以免產生嚴重的邏輯錯誤。