变量交换的几种常见方法.docx

上传人:太** 文档编号:94169266 上传时间:2023-07-23 格式:DOCX 页数:8 大小:13.52KB
返回 下载 相关 举报
变量交换的几种常见方法.docx_第1页
第1页 / 共8页
变量交换的几种常见方法.docx_第2页
第2页 / 共8页
点击查看更多>>
资源描述

《变量交换的几种常见方法.docx》由会员分享,可在线阅读,更多相关《变量交换的几种常见方法.docx(8页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、变量交换的几种常见方法前几天发现了一个问题:有人告诉我,要进行变量交换,就必须 引入第三变量!假设我们要交换a和b变量的值,如果写成int a = 5zb=10;a二b;b=a;那么结果就是两个都是10 ,理由不言而喻。所以就应该引入第三变量,在a的值被覆盖之前就把a的值保留好。int a = 5zb=10ztmp;tmp=a;a = b;b=tmp;这样,就要引入了第三个变量,然而,我们能不能不引入第三变量来实现变量交换 呢?答案自然是肯定的,首先我们可以这样设想,如果a的值被覆盖了,那么就没法知道 b应该放什么值了,所以,我们要保留a的值,因此我们可以把a和b的值合起来,放在a里,再把合

2、起来的值分开,分别放到b和a中:int a = 5,b=10;a=a+b; /a=15,b=10b=a-b; /a = 15,b=5a=a-b; /a=10,b=5但是这样做有一个缺陷,假设它运行在vc6环境中,那么int的大小是4 Bytes ,所 以int变量所存放的最大值是2A31-1即2147483647 ,如果我们令a的值为 2147483000 , b的值为1000000000 ,那么a和b相力口就越界了。事实上,从实际的运行统计上看,我们发现要交换的两个变量,是同号的概率很大, 而且,他们之间相减,越界的情况也很少,因此我们可以把上面的加减法互换,这样使得 程序出错的概率减少:i

3、nt a = 5,b=10;a-=b; /a=-5,b=10b+=a; /a=15,b=5a+ = b; /a=10,b=5通过以上运算,a和b中的值就进行了交换。表面上看起来很简单,但是不容易想 到,尤其是在习惯引入第三变量的算法之后。它的原理是:把a、b看做数轴上的点,围绕两点间的距离来进行计算。具体过程:第一句a-二b求出ab两点的距离,并且将其保存在a中;第二句 “b+二a求出a到原点的距离(b到原点的距离与ab两点距离之差),并且将其保存 在b中;第三句a+=b求出b到原点的距离(a到原点距离与ab两点距离之和), 并且将其保存在a中。完成交换。此算法与引入第三变量的算法相比,多了三

4、个计算的过程,但是没有借助临时变量, 因此我们称之为算术交换算法。因外上面的算术交换算法有导致变量溢出的危险,所以我们再想办法引入一个逻辑运 算位异或,也能得到交换效果,而且不会导致溢出。位异或运算符是人,它的作用是按照每个位进行异或运算,异或运算有一个特通过异或运算能够使数据中的某些位翻转,其他位不变。这就意味着任意一个数与任 意一个给定的值连续异或两次,值不变。即:aAbAb=ao将a=aAb代入b=aAb则得 b=abAb二a洞理可以得到 a=bAaAa=b;如存在c=a人b;这种关系后,任意给出两个变量进行位异或运算,都能得到剩下的第 三个变量:a = bAc;b=aAc;c=aAb;

5、因此位异或也常用于密码学中。因为它是按位进行运算的,因此没有溢出的情况,在这里,我们运用位异或运 算来交换变量的值。int a = 10zb=12; /a=1010Ab=1100;a=aAb;/a=0110Ab=1100;b=aAb;/a=0110Ab=1010;a=aAb; /a=1100=12;b=1010;轻松完成交换。理论上重载人运算符,也可以实现任意结构的交换另外,如果变量较大,或者交换较复杂的类,这样交换也是很慢的,因此可以使用指 针交换,因为对地址的操作实际上进行的是整数运算,比如:两个地址相减得到一个整数,表 示两个变量在内存中的储存位置隔了多少个字节;地址和一个整数相加即a+

6、 10”表示 以a为基地址的在a后10个a类数据单元的地址。所以理论上可以通过和算术算法类似 的运算来完成地址的交换,从而达到交换变量的目的。即:int *a,*b;*a=new int(10);*b=new int(20); /&a=0x00001000h,&b=0x00001200ha=(int*)(b-a); /8iamp;a=0x00000200h,&b=0x00001200hb=(int*)(b-a); /&a=0x00000200h,&b=0x00001000ha=(int*)(b+int(a); /&a=0x00001200h,&a

7、mp;b=0x00001000h通过以上运算a、b的地址真的已经完成了交换,且a指向了原先b指向的值,b指 向原先a指向的值了吗?上面的代码可以通过编译,但是执行结果却令人匪夷所思!原因 何在?首先必须了解,操作系统把内存分为几个区域:系统代码/数据区、应用程序代码/数 据区、堆栈区、全局数据区等等。在编译源程序时,常量、全局变量等都放入全局数据 区,局部变量、动态变量则放入堆栈区。这样当算法执行到a=(int*)(b-a)时,a的值 并不是0x00000200h ,而是要加上变量a所在内存区的基地址,实际的结果是: 0x008f0200h ,其中0x008f即为基地址,0200即为a在该内存

8、区的位移。它是由编译 器自动添加的。因此导致以后的地址计算均不正确,使得a,b指向所在区的其他内存单 元。再次,地址运算不能出现负数,即当a的地址大于b的地址时,b-a<0 ,系统自动 采用补码的形式表示负的位移,由此会产生错误,导致与前面同样的结果。有办法解决吗?当然有,以下是改进的算法:if(a<b)a=(int*)(b-a);b=(int*)(b-(int(a)&0x0000ffff);a=(i nt*) (b+(i n t (a) &a m p;OxOOOOffff);)else(b=(int*)(a-b);a=(int*)(a-(int(b)&OxOOOO

9、ffff);b=(int*)(a+(int(b)&OxOOOOffff);)算法做的最大改进就是采用位运算中的与运算,int(a)&OxOOOOffff, ,因为地 址中高16位为段地址,后16位为位移地址,将它和OxOOOOffff进行与运算后,段地址 被屏蔽,只保留位移地址。这样就原始算法吻合,从而得到正确的结果。此算法同样没有使用第三变量就完成了值的交换,与算术算法比较它显得不好理解, 但是它有它的优点即在交换很大的数据类型时,它的执行速度比算术算法快。因为它交换 的时地址,而变量值在内存中是没有移动过的。以上四个算法均实现了不借助其他变量来完成两个变量值的交换,相比较而言算术算 法和位算法计算量相当,地址算法中计算较复杂,却可以很轻松的实现大类型(比如自定 义的类或结构)的交换,而算术算法和位算法只能进行整形数据的交换,而引用第三变量 的算法无疑是最好的,能够解决任意类型的交换问题。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 应用文书 > 解决方案

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁