在码代码的过程中可能会经常涉及到需要交换两变量的值,有时甚至需要大量频繁地交换一系列变量的值,在网上收集了一些算法,附带上自己的一点粗浅分析,且作备忘。
1、通用经典算法
int temp,a,b;
temp=a;
a=b;
b=temp;
通过引入第三变量temp来达到交换a、b值的目的,容易理解、不会产生歧义并且可移植性强,必要时甚至可以使用寄存器变量register int temp;以达到快速存取的目的,是十分经典的算法,每一个初学者都会认识到的算法,是赋值语句的经典应用。唯一不足就是借助了临时变量,占用了内存,并进行赋值操作的过程中造成了不必要的开销。
以下几种算法均不需借助临时变量来完成两变量值的交换,每种算法各有利弊。
2、位运算算法
int a,b;
a=a^b; //1
b=a^b; //2
a=a^b; //3
这个算法的实现借助于关于位运算的几个规律:
1)a^a=0
2)a^(b^c)=(a^b)^c
3)a^0=a
假设a、b代表的值分别为p、q
a | b | |
p | q | |
① | p^q | q |
② | p^q | p^q^q |
③ | (p^q)^(p^q^q) | p^q^q |
应用规律算出结果便知a=q b=p 达到了交换的目的了。
这个算法表达式也可以简化为
a^=b^=a^=b;
这样,我们便可轻松地通过宏定义来实现a、b互换函数swap(a,b):
#define swap(a,b) a^=b^=a^=b;
这个算法的缺陷在于,当a、b为同一个数,即a、b拥有相同的地址时(而非a==b这种情况),将会使a、b的值置零,在使用这个算法的时候要特别注意,例如如下情况:
#include
#define swap(a,b) a^=b^=a^=b;
int main()
{
int a[2]={1,2};
swap(a[0],a[1]);
printf("%d %d\n",a[0],a[1]);
swap(a[0],a[0]);
printf("%d %d\n",a[0],a[1]);
return 0;
}
此时输出的结果为
2 1
0 1
意味着a[1]与a[0]的值正确交换,但是a[0]的值在随后的操作中被置零了,只要对该算法稍作分析便可明白出现这种情况的原因,所以,如果采用这个算法实现,在编程的过程中也无法确切知道swap的两变量是否是同一个变量,使用前先进行判断为好。
int a,b;
a=a+b;
b=a-b;
a=a-b;
只要稍作分析便不难理解该算法的实现过程,该算法的主要弊端在于,当a+b≥MAX_INT时,将会造成数据溢出,但溢出是相对的,在加的过程后又进行了减运算,将导致最后的结果符合预期,只不过存在不安全因素,该方法同样用的比较普遍。下面通过一个实例来说明:
#include
int main()
{
unsigned short a=65534,b=2; //无符号短整型表示数范围为0~65535
a=a+b;
printf("%d %d\n",a,b);
b=a-b;
printf("%d %d\n",a,b);
a=a-b;
printf("%d %d",a,b);
}
输出分别为:
4、栈运算算法
int exchange(int x,int y)
{
stack S;
push(S,x);
push(S,y);
x=pop(S);
y=pop(S);
}
栈运算的方法不需要解释,没有使用第三个变量但是使用了栈操作并且使用了函数来完成,就复杂性而言得不偿失,并不推荐。