交换两个整数的值

交换两个整数的值采用第三方变量的方法非常简单,在C语言的入门学习中就已经用烂。但是我还是列出来一下:

void Swap1(int *a, int *b)
{
	int temp;
	temp = *a;
	*a = *b;
	*b = temp;
}
这里要注意:函数名Swap1不能写成swap,因为swap名可能会与库函数中的swap冲突。

第三方变量的方式还有——引用的方法

void Swap2(int &a,int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}


如果不使用第三方变量,怎么办?

一. 用异或!

比如:

void Swap3(int &a,int &b)
{
	a ^= b;
	b ^= a;
	a ^= b;
}
怎么样理解呢?
 两个性质:

1)a^b = b^a;

2)  a^a = 0

程序中 第一行 a ^= b 可以表示为a = a^b;

第二行b = b^(a^b) = a^(b^b) = a

第三行a = (a^b)^a = (a^a)^b = b

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

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


 这样做可以避免如下情况越界的问题

比如

a = a + b;

b = a - b;

a = a - b;

这样做实现交换很有可能a+b越界溢出出错。


异或交换缺陷

比如说:

int i = 3;
int *a = &i;
int *b = a;
void Swap3(a,b)
{
	a ^= b;
	b ^= a;
	a ^= b;
}
cout<<"*a = "<<*a<<" *b = "<<*b<<endl;
这段代码输出应该是:a = 2, b =2,因为两个同样的数经过交换应该还是一样的(=2)。但是由于这里a,b都指向i的位置,所以这里Swap3(a,b)=i^i=0;结果等于“0”!

为了避免这种情况发生,我们首先得判断这两个数是不是相等

程序自当改为:

void Swap4(int &a, int &b)
{
	if(a == b) return; //防止&a,&b指向同一个地址;不然结果会错误。
	a ^= b;
	b ^= a;
	a ^= b;
}


当然,异或的方式也可以写成这样的简写形式

 *a ^= *b^= *a ^= *b;


二. 汇编

int x = 12, y= 19;
_asm
{
    push x; 
    push y; 
    pop x; 
    pop y; 
} 
printf("x is %d, y is %d /n", x,y);
没有尝试,仅列出来而已,很好理解

其实,直接调用 swap库函数是最方便的。

测试代码:

#include <iostream>
#include <vector>
using namespace std;

void Swap1(int *a1, int *b1)
{
	int temp;
	temp = *a1;
	*a1 = *b1;
	*b1 = temp;
}

void Swap2(int &a,int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

void Swap3(int &a,int &b)
{
	a ^= b;
	b ^= a;
	a ^= b;
}

void Swap4(int &a, int &b)
{
	if(a == b) return; //防止&a,&b指向同一个地址;不然结果会错误。
	a ^= b;
	b ^= a;
	a ^= b;
}

int main()
{
	///
	///
	/*                                                           */
	/*               Edit by Call me Yang                        */
	/*                  2014.04.23                               */
	/*                                                           */
	///
	//                                                           //
	// 这里只讲第一种方式Swap1(&a,&b)中,&a和&b是变量a和b的地址  //
	// 形参a1与b1分别复制主函数a与b的值,就是拷贝副本,即a1与a的  //
	// 指向相同,b1与b的指向相同,可以写成int *a1;a1 = &a;将a的地  //
	// 址赋给a1,b同理。而形参函数中实际操作使用*a1 和*b1,将改  //
	// 变a1和b1指向的地址的值,即地址中的数,达到交换目的        //
	//                                                           //
	///
	//第一种方式
	cout<<"第一种方式"<<endl;
	int a = 2;
	int b = 3;
	cout<<"交换前a的地址 = "<<&a<<" b的地址 = "<<&b<<endl;
	Swap1(&a,&b);
	cout<<"a = "<<a<<" b = "<<b<<endl;
	cout<<"交换后a的地址 = "<<&a<<" b的地址 = "<<&b<<endl<<endl;
	///
	//第二种方式
	cout<<"第二种方式"<<endl;
	int c = 2;
	int d = 3;
	cout<<"交换前c的地址 = "<<&c<<" d的地址 = "<<&d<<endl;
	Swap2(c,d);
	cout<<"c = "<<c<<" d = "<<d<<endl;
	cout<<"交换后c的地址 = "<<&c<<" d的地址 = "<<&d<<endl<<endl;;
	///
	//第三种方式
	cout<<"第三种方式"<<endl;
	int e = 2;
	int f = 3;
	cout<<"交换前e的地址 = "<<&e<<" f的地址 = "<<&f<<endl;
	Swap3(e,f);
	cout<<"e = "<<e<<" f = "<<f<<endl;
	cout<<"交换后e的地址 = "<<&e<<" f的地址 = "<<&f<<endl<<endl;
	//**********************
	int e1 = 3;
	//int f1 = 3;
	cout<<"交换前e1的地址 = "<<&e1<<endl;//<<" f1的地址 = "<<&f1<<endl;
	//Swap3(e1,f1);
	Swap3(e1,e1);
	cout<<"e1 = "<<e1<<" f1 = "<<e1<<endl;
	cout<<"交换后e1的地址 = "<<&e1<<" f1的地址 = "<<&e1<<endl;
	cout<<"由此可以看出两数相等时的缺陷!"<<endl<<endl;
	///
	//第四种方式
	cout<<"第四种方式"<<endl;
	int g = 3;
	int h = 3;
	cout<<"交换前g的地址 = "<<&g<<" h的地址 = "<<&h<<endl;
	Swap4(g,h);
	cout<<"g = "<<g<<" h = "<<h<<endl;
	cout<<"交换后g的地址 = "<<&g<<" h的地址 = "<<&h<<endl<<endl;
	///
	//直接调用swap
	//第五种方式
	cout<<"第五种方式"<<endl;
	int i = 2;
	int j = 3;
	cout<<"交换前g的地址 = "<<&i<<" j的地址 = "<<&j<<endl;
	swap(i,j);
	cout<<"i = "<<i<<" j = "<<j<<endl;
	cout<<"交换后i的地址 = "<<&i<<" j的地址 = "<<&j<<endl<<endl;
	///
	//使用容器
	//第六种方式
	cout<<"第六种方式"<<endl;
	int x = 2,y = 3;
	vector <int> vec;
	vec.push_back(x);
	vec.push_back(y);
	cout<<"交换前x的地址 = "<<&x<<" y的地址 = "<<&y<<endl;
	swap(vec[0],vec[1]);
	//swap(x,y);
	cout<<vec[0]<<" "<<vec[1]<<endl;
	cout<<"交换后x的地址 = "<<&x<<" y的地址 = "<<&y<<endl<<endl;
	///
	system("pause");
	return 0;
}

结果显示如下:






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值