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

20 篇文章 0 订阅
8 篇文章 0 订阅

假设两个数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;




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值