1. 程式人生 > >交換兩個整型數各種方法總結

交換兩個整型數各種方法總結

原文地址

交換兩個整型數是C/C++中最常見的操作。

實現這個操作的方法很多。

最基本的方法就是使用一個臨時變數,具體的程式碼如下:

int a,b;
int tmp;
tmp=a;
a=b;
b=tmp;

 如果以函式的形式寫出來的話就是:

void swap(int *a,int *b)
{
int tmp;
tmp=*a;
*a=*b;
*b=tmp;
}

 在C++中,可以使用引用來實現的比較優雅:

void swap(int& a,int &b)
{
int tmp;
tmp=a;
a=b;
b=tmp;
}

 另外,還經常出現的一種情況是不使用臨時變數來交換兩個整型數,一般常見的方法有兩種:加法和異或運算,具體如下表所示:

void swap1(int& x,int& y)
{
x=x+y;
y=x-y;
x=x-y;
}


void swap2(int &x,int &y)
{
x=x-y;
y=x+y;
x=y-x;
}


void swap3(int& x,int& y)
{
x ^= y;
y ^= x;
x ^= y;
}


x和y同號的情況下容易溢位

x和y異號的情況下容易溢位

 

左邊的兩種交換也存在問題就是整數的溢位。

還有一種情況就是輸入是swap(a,a)的情況。這樣的話就會出問題。

所以更嚴謹的做法如下:

void swap4(int &x,int &y)
{
if(x==y)
return ;
if((x>0&&y>0)||(x<0&&y<0)) {
x=x-y;
y=x+y;
x=y-x;
}
else{
x=x+y;
y=x-y;
x=x-y;
}
}


void swap5(int &x,int &y)
{
if(x==y)
return;
x^=y;
y^=x;
x^=y;
}


void swap7(int &x,int &y)
{
if(x==y)
return;
y=x+y-(x=y);
}

 引申:

在C++中支援模板操作,所以,可以利用這個寫一個通用的swap操作:

template <class T>
void swap ( T& a, T& b )  
{  
T c(a); 
a=b; 
b=c;  
} 


 這個其實是C++標準模板庫中函式。該函式可以交換任意兩個型別: 

// swap algorithm example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main () {
  int x=10, y=20;                         // x:10 y:20
  swap(x,y);                              // x:20 y:10

  vector<int> first (4,x), second (6,y);  // first:4x20 second:6x10
  swap(first,second);                     // first:6x10 second:4x20

  cout << "first contains:";
  for (vector<int>::iterator it=first.begin(); it!=first.end(); ++it)
    cout << " " << *it;
//first contains: 10 10 10 10 10 10
  cout << endl;
  return 0;
}

 除此之外,在標準C++中string,vector,map,set等容器都是有swap函式的。

 下面是一些簡單的例子:

 

// swap strings
#include <iostream>
#include <string>
using namespace std;
main ()
{
  string buyer ("money");
  string seller ("goods");

  cout << "Before swap, buyer has " << buyer;
  cout << " and seller has " << seller << endl;

  seller.swap (buyer);

  cout << " After swap, buyer has " << buyer;
  cout << " and seller has " << seller << endl;
//Before swap, buyer has money and seller has goods
//After swap, buyer has goods and seller has money
  return 0;
}


//  swap vectors #include <iostream>
#include <vector>
using  namespace std;

int main ()
{
  unsigned  int i;
  vector< int> first ( 3, 100);    //  three ints with a value of 100
  vector< int> second ( 5, 200);   //  five ints with a value of 200

  first.swap(second);

  cout <<  " first contains: ";
   for (i= 0; i<first.size(); i++) cout <<  "   " << first[i];

  cout <<  " \nsecond contains: ";
   for (i= 0; i<second.size(); i++) cout <<  "   " << second[i];
// first contains: 200 200 200 200 200 
// second contains: 100 100 100 
  cout << endl;

   return  0;
}

//  swap maps
#include <iostream>
#include <map>
using  namespace std;

int main ()
{
  map< char, int> foo;
  map< char, int> bar;
  map< char, int>::iterator it;

  foo[ ' x ']= 100;
  foo[ ' y ']= 200;

  bar[ ' a ']= 11;
  bar[ ' b ']= 22;
  bar[ ' c ']= 33;

  foo.swap(bar);

  cout <<  " foo contains:\n ";
   for ( it=foo.begin() ; it != foo.end(); it++ )
    cout << (*it).first <<  "  =>  " << (*it).second << endl;

  cout <<  " bar contains:\n ";
   for ( it=bar.begin() ; it != bar.end(); it++ )
    cout << (*it).first <<  "  =>  " << (*it).second << endl;

   return  0;
}
foo contains:
a =>  11
b =>  22
c =>  33
bar contains:
x =>  100
y =>  200

//  swap sets
#include <iostream>
#include < set>
using  namespace std;

main ()
{
   int myints[]={ 12, 75, 10, 32, 20, 25};
   set< int> first (myints,myints+ 3);      //  10,12,75
   set< int> second (myints+ 3,myints+ 6);   //  20,25,32
   set< int>::iterator it;

  first.swap(second);

  cout <<  " first contains: ";
   for (it=first.begin(); it!=first.end(); it++) cout <<  "   " << *it;

  cout <<  " \nsecond contains: ";
   for (it=second.begin(); it!=second.end(); it++) cout <<  "   " << *it;

  cout << endl;

   return  0;
}
first contains:  20  25  32
second contains:  10  12  75 複製程式碼

 

另外,還有不使用臨時變數交換N個整型數的操作, 

有N(N>=2)個變數,不使用臨時變數,如何順次交換它們的值?能否只用一條語句實現?如   +---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
| 1 | 2 | 3 | 4 | 5 |
+---+---+---+---+---+   要把它變為   +---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
| 2 | 3 | 4 | 5 | 1 |
+---+---+---+---+---+   怎樣實現?   首先,我們考慮用異或實現兩個變數的交換,可參考我的這篇文章《 不用臨時變數交換兩個數的值》。用C++寫函式如下:  

int &swap(int &a, int &b)
{
    b = b ^ a;
    a = a ^ b;
    b = b ^ a;

    return b;
}

然後可以把程式碼優化為:

int &swap(int &a, int &b)
{
    b ^= a;
    a ^= b;
    b ^= a;

    return b;
}

繼續優化,把三句壓縮為一句,如下:

int &swap(int &a, int &b)
{
    b ^= a ^= b ^= a;
    
    return b;
}

還可再優化,如下:

int &swap(int &a, int &b)
{
    return (b ^= a ^= b ^= a);
}

現在來順次交換5個變數的值,如下:

swap(a, b);        //返回b

swap(b, c);        //返回c

swap(c, d);        //返回d

swap(d, e);        

既然有返回值,那麼可以寫成鏈式的,如下:

swap(a, b);                                 //返回b

swap(swap(a, b), c);                        //返回c

swap(swap(swap(a, b), c), d);               //返回d

swap(swap(swap(swap(a, b), c), d), e);        

現在,讓我們來把swap函式依次用相應的函式體替換掉,如下:

e ^= d ^= e ^= swap(swap(swap(a, b), c), d);

e ^= d ^= e ^= d ^= c ^= d ^= swap(swap(a, b), c);

e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= swap(a, b);

e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= b ^= a ^= b ^= a;

好了,最後一個語句就實現了順次交換五個變數的值,寫程式驗證如下: 

 

複製程式碼 #include <stdio.h>
#define PRINT(A) do {/
    printf( " %d/n ", A);/
    }  while ( 0)
int main()
{
     int a =  1;
     int b =  2;
     int c =  3;
     int d =  4;
     int e =  5;

//     b ^= a ^= b ^= a;         //  swap(a, b)
//     c ^= b ^= c ^= b;         //  swap(b, c)
//     d ^= c ^= d ^= c;         //  swap(c, d)
//     e ^= d ^= e ^= d;         //  swap(d, e)

    e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= b ^= a ^= b ^= a;

    PRINT(a);
    PRINT(b);
    PRINT(c);
    PRINT(d);
    PRINT(e);

     return  0;
}