1. 程式人生 > >java異或運算交換兩個數的陷阱

java異或運算交換兩個數的陷阱

我們知道,用異或運算可以不用定義中間變數就可以交換兩個數。如下:
<span style="font-size:14px;">int a=2;
int b=3;

System.out.println("交換前:a="+a+"  b="+b);

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

System.out.println("交換後:a="+a+"  b="+b);</span>

輸出的結果是:

交換前:a=2  b=3

交換後:a=3  b=2

這樣看來,使用異或運演算法則交換兩個數的方法確實很好用。但是我們在某些特殊的地方使用它就要小心了,比如我們在選擇排序演算法中使用它時:

<span id="_xhe_cursor"></span><span style="font-size:12px;">package com.test;

public class Test {
	public static void main(String[] args) {
		int a[] = { 5, 3, 7, 9, 0, 2, 1, 4, 6, 8 };
		Select select = new Select();
		select.sort(a);
		// 遍歷輸出排好的陣列
		for (int i : a) {
			System.out.print(i + " ");
		}
	}
}

// 選擇排序類
class Select {
	public void sort(int a[]) {
		for (int j = 0; j < a.length - 1; j++) {
			int min = a[j];// 最小的值
			int minLndex = j;// 最小值的下標
			for (int k = j + 1; k < a.length; k++) {
				if (min > a[k]) {
					min = a[k];
					minLndex = k;
				}
			}
			// 使用異或運算交換兩個數
			a[j] = a[j] ^ a[minLndex];
			a[minLndex] = a[j] ^ a[minLndex];
			a[j] = a[j] ^ a[minLndex];
		}
	}
}</span>

輸出的結果是:0 1 2 3 4 5 6 0 8 9

為什麼呢?

其實我們知道,異或運算a^a=0,我們仔細分析一下可以發現在選擇排序演算法中就有a^a的情況,所以出現上面這樣的結果也就不奇怪啦。

對於以上bug,我們可以這樣解決:

在交換之前先判斷

<pre class="java" name="code">if(a[j]!=a[minLndex])
{
	a[j]=a[j]^a[minLndex];
	a[minLndex]=a[j]^a[minLndex];
	a[j]=a[j]^a[minLndex];
}

這樣,輸出的結果就是正確的了。

總結:以後用到異或運算交換兩個數時,首先要想到所有數中有沒有自身跟自身交換的情況