1. 程式人生 > >Java快速交換兩個數的值

Java快速交換兩個數的值

1:通過使用異或運算,可以快速將兩個數的值交換:原理如下:
    我們知道異或是相同取0相反取1,如:0101異或1101的結果是1000。如對兩個數,經過三次進行異或執行後的結果是這兩個數的值互換。如 a =       0101, b=1101,則進行的操作如下:
           第一次異或運算: a = a ^b = 1000
           第二次異或運算: b = a^b = 0101
           第三次異或運算: a = a^b = 1101
至此,a和b這兩個數的值已經互換了,並且沒有使用到額外的儲存空間。
那麼,能不能直接寫一個函式直接將a和b作為值引數進行數值互換呢。答案是否定的。我們知道函式引數的以值傳遞方式是對引數的值拷貝到當前函式棧幀中,相當於對傳遞過來的引數作一個記憶體拷貝吧。這樣,傳遞過來的引數值改變並沒有影響到原來與引數的變數或常量的值。如果是傳遞過來的是引用,結果就不一樣了。
使用java語言簡單實現如下:
public static void quickSwap(int vaules[]){
   values[0] = values[0]^values[1];
   values[1] = values[0]^values[1];
   values[0] = values[0]^values[1];
}
2:還可以將你要交換的引數作為物件的一個變數來交換,例如:
class ABC{
int abc;
}
public class ChangeObject {
public static void main(String args[]){
ABC a1=new ABC();
ABC a2=new ABC();
a1.abc=111;
a2.abc=222;
System.out.println("a.abc:"+a1.abc+" b.abc:"+a2.abc);
change(a1,a2);
System.out.println("a.abc:"+a1.abc+" b.abc:"+a2.abc);
}
public static void change(ABC a,ABC b){
ABC temp=new ABC();
temp.abc=a.abc;
a.abc=b.abc;
b.abc=temp.abc;
}
}
3:在程式中實現交換兩個數的功能並不複雜,但如果不使用中間變數,就需要動一下腦筋。在本文介紹了兩個方法(其實原理都是一個)。其基本原理就是數的中和。 也就是說,通過某種運算(二元運算)將a和b兩個數變成一個數,並儲存在其中一個變數中。然後再通過同樣的運算子將a或b中和掉。這樣實際上是利用了a或 b本身作為了中間變數。
    先看第一個演算法。
static class Num
{
    int a;
    int b;
}
public static void swap1(Num num)
{
    num.a = num.a + num.b;
    num.b = num.a - num.b;
    num.a = num.a - num.b;
}

上面程式碼通過“+”運算子將a和b的運算結果賦給了a(這時a是中間變數)。然後再計算b,這時a的值已經是(a+b)了,因此,a再減b就是原來的a。 而這時b已經是原來的a了,因此,再用運算後的a(實際上是a+b)減運算後的b(實際上是原來的a),就是原來的b了,最後將這個b賦值給a。
    實際上,我們還可以使用“*”、“/”等符號來實現同樣的效果,程式碼如下:
public static void swap2(Num num)
{
    num.a = num.a * num.b;
    num.b = num.a / num.b;
    num.a = num.a / num.b;
}
public static void swap3(Num num)
{
    num.a = num.a - num.b;
    num.b = num.a + num.b;
    num.a = num.b - num.a;
}
    上面程式碼在Java中沒有什麼問題(但使用“/”時,分母和分子不能為0)。就算溢位也會得到正確的結果,但有某些語言中(如C語言),可能會丟擲溢位錯誤,不了避免這種錯誤。可以加判斷,程式碼如下:
public static void swap4(Num num)
{
    // 不同符號
    if (num.a * num.b <= 0)
    {
        num.a = num.a + num.b;
        num.b = num.a - num.b;
        num.a = num.a - num.b;
    }
    else
    {
        num.a = num.a - num.b;
        num.b = num.a + num.b;
        num.a = num.b - num.a;
    }
}
    當然,我們還有更好的方法,就是使用異或運算子,我們知道,任何數與0異或後仍然為它本身,兩個相同的數異或後為0。根本這種特性,可以有如下程式碼。
public static void swap5(Num num)
{
    num.a = num.a ^ num.b;
    num.b = num.a ^ num.b;
    num.a = num.a ^ num.b;
}
Java函式在傳遞過程中只能夠傳值,不能傳址。這樣,函式的引數在函式內部做任何變化就都不會反映到外部呼叫者來。所以解決之道就是要找到要交換物件的引用。對於普通的值型別,像int或者double這樣的可以改傳他們的包裝類Integer和Double。而對於本來就是引用型別的物件,則需要對他們再包一層。一個好的方法就是將引數列表改成陣列
import java.io.*;
public class Compare
{
public static void change(int[] a) throws Exception
{
int temp=0;
temp=a[0];a[0]=a[1];a[1]=temp;
}
public static void main(String args[]) throws Exception
{
int[] a = new int[2];
System.out.println("輸入a:");
InputStreamReader inreader=new InputStreamReader(System.in);
BufferedReader breader=new BufferedReader(inreader);
a[0]=Integer.parseInt(breader.readLine());
System.out.println("輸入b:");
a[1]=Integer.parseInt(breader.readLine());
System.out.println("交換前a="+a[0]+" 交換前b="+a[1]);
change(a);
System.out.println("交換後a="+a[0]+" 交換後b="+a[1]);
}
}
4:這種類性的交換,實屬罕見。很經典的,如果誰知道請幫忙解釋一下。
public class Test
{   
  public static void main(String[]args)
  {
        int a=10;
        int b=5;
     System.out.println((a=(b+(b=a)*0))+"b:"+b);
   } 
}