我们在刚学C语言时,做两个变量的交换时,常常借助第三变量。其原始代码如下:
0)原始方法
int a ,b ,t;
a =6 ;
b=9 ;
t = a ;
a = b ;
b = t ;
这个算法最大的缺点就是借用了临时变量。
那么,我们看看不借助临时变量的交换算法有哪些:
1)算术运算法
int a, b ;
a = 6 ;
b = 9 ;
a = a + b ; //a = 15
b = a - b ; // b =6 , a =15
a = a -b ; // b = 6 ,a = 9
这个我们容易想到
2) 位运算
int a = 3; // a = 0011
int b = 4; // b = 0100
a = a^b; // a = 0011^0100 = 0111
b = a^b; // b = 0111^0100 = 0011=3
a = a^b; // a = 0111 ^ 0011= 0100 =4
此算法能够实现是由异或运算的特点决定的,通过异或运算能够使数据中的某些位翻转,其他位不变。这就意味着任意一个数与任意一个给定的值连续异或两次,值不变,(理论上重载“^”运算符,也可以实现任意结构的交换)
3)指针地址操作
因为对地址的操作实际上进行的是整数运算,比如:两个地址相减得到一个整数,表示两个变量在内存中的储存位置隔了多少个字节;地址和一个整数相加即“a+10”表示以a为基地址的在a后10个a类数据单元的地址。所以理论上可以通过和算术算法类似的运算来完成地址的交换,从而达到交换变量的目的。即:
int*a,*b;
*a=newint(10);
*b=newint(20);//&a=0x00001000h,&b=0x00001200h
a=(int*)(b-a);//&a=0x00000200h,&b=0x00001200h
b=(int*)(b-a);//&a=0x00000200h,&b=0x00001000h
a=(int*)(b+int(a));//&a=0x00001200h,&b=0x00001000h
4)升级的xor算法
#include <stdio.h>
void xorSwap (int* x, int* y) {
if (x != y) { //ensure that memory locations are different
*x ^= *y;
*y ^= *x;
*x ^= *y;
}}
int main(void) {
int a = 3;
int b = 4;
xorSwap(&a,&b);
printf("%d,%d\n",a,b);
return 0;
}
测试是为了确保x和y具有不同的内存位置(而不是不同的值)。这是因为(p xor p) = 0如果x和y共享相同的内存位置,当一个设置为0时,两者都设置为0.当* x和* y都为0时,* x和* y上的所有其他xor操作将相等0(因为它们是相同的),这意味着该函数将* x和* y都设置为0。
5)栈实现。不多解释了,栈和相关函数定义省去
intexchange(intx,inty)
{
stack S;
push(S,x);
push(S,y);
x=pop(S);
y=pop(S);
}
总结一下:
以上算法均实现了不借助其他变量来完成两个变量值的交换,相比较而言算术算法和位算法计算量相当,地址算法中计算较复杂,却可以很轻松的实现大类型(比如自定义的类或结构)的交换,而前两种只能进行整形数据的交换(理论上重载“^”运算符,也可以实现任意结构的交换)。