不借助第三个变量交换两个整数

假设两个数x和y,则有:

方法1,算术运算(加减):

x=x+y;  //x暂存两数之和 y=x-y;  //y为两数之和减去y,即原来的x x=x-y;  //x为两数之和减去现在的y(原来的x),变成原来的y

方法2,逻辑运算(异或):

x^=y; //x先存x和y两者的信息 y^=x; //保持x不变,利用x异或反转y的原始值使其等于x的原始值 x^=y; //保持y不变,利用x异或反转y的原始值使其等于y的原始值

关于异或运算要牢记两个原则:

任何一位二进制数同 1 异或都会变成另外一个(0 同 1 异或的结果是 1,1 同 1 异或的结果是 0)
任何一位二进制数同 0 异或都保持不变(0 同 0 异或的结果是 0,1 同 0 异或的结果是 1)

实现这个操作的方法很多。

最基本的方法就是使用一个临时变量,具体的代码如下:

int a,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异号的情况下容易溢出

 

左边的两种交换也存在问题就是整数的溢出。

所以更严谨的做法如下:

《不借助第三个变量交换两个整数》 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);
} 《不借助第三个变量交换两个整数》

【扩展】

另外,还有不使用临时变量交换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;

    原文作者:sam_justin
    原文地址: https://blog.csdn.net/samjustin1/article/details/52138733
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞