交换两个整型数的方法

交换两个整型数是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;
}

 

参考:http://blog.csdn.net/lpt19832003/article/details/5334688

posted @ 2012-05-16 20:38  Mr.Rico  阅读(13646)  评论(2编辑  收藏  举报