交换两个整数的值采用第三方变量的方法非常简单,在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;
}
结果显示如下: