- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
变量交换几种常见方法
变量交换几种常见方法
前几天发现了一个问题:有人告诉我,要进行变量交换,就必须引入第三变量!
假设我们要交换a和b变量的值,如果写成
int a=5,b=10;
a=b;
b=a;
那么结果就是两个都是10,理由不言而喻。
所以就应该引入第三变量,在a的值被覆盖之前就把a的值保留好。
int a=5,b=10,tmp;
tmp=a;
a=b;
b=tmp;
这样,就要引入了第三个变量,然而,我们能不能不引入第三变量来实现变量交换呢?
答案自然是肯定的,首先我们可以这样设想,如果a的值被覆盖了,那么就没法知道b应该放什么值了,
所以,我们要保留a的值,因此我们可以把a和b的值合起来,放在a里,再把合起来的值分开,分别放到b和a中:
int a=5,b=10;
a=a+b; //a=15,b=10
b=a-b; //a=15,b=5
a=a-b; //a=10,b=5
但是这样做有一个缺陷,假设它运行在vc6环境中,那么int的大小是4 Bytes,所以int变量所存放的最大值是2^31-1即2147483647,如果我们令a的值为2147483000,b的值为1000000000,那么a和b相加就越界了。
事实上,从实际的运行统计上看,我们发现要交换的两个变量,是同号的概率很大,而且,他们之间相减,越界的情况也很少,因此我们可以把上面的加减法互换,这样使得程序出错的概率减少:
int a=5,b=10;
a-=b; //a=-5,b=10
b+=a; //a=15,b=5
a+=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中。完成交换。
此算法和引入第三变量的算法相比,多了三个计算的过程,但是没有借助临时变量,因此我们称之为算术交换算法。
因外上面的算术交换算法有导致变量溢出的危险,所以我们再想办法引入一个逻辑运算——位异或,也能得到交换效果,而且不会导致溢出。
位异或运算符是“^”,它的作用是按照每个位进行异或运算,异或运算有一个特点:
通过异或运算能够使数据中的某些位翻转,其他位不变。这就意味着任意一个数和任意一个给定的值连续异或两次,值不变。 即:a^b^b=a。将a=a^b代入b=a^b则得b=a^b^b=a;同理可以得到a=b^a^a=b;
如存在c=a^b;这种关系后,任意给出两个变量进行位异或运算,都能得到剩下的第三个变量:
a=b^c;
b=a^c;
c=a^b;
因此位异或也常用于密码学中。
因为它是按位进行运算的,因此没有溢出的情况,在这里,我们运用位异或运算来交换变量的值。
int a=10,b=12; //a=1010^b=1100;
a=a^b; //a=0110^b=1100;
b=a^b; //a=0110^b=1010;
a=a^b; //a=1100=12;b=1010;
轻松完成交换。
理论上重载“^”运算符,也可以实现任意结构的交换
另外,如果变量较大,或者交换较复杂的类,这样交换也是很慢的,因此可以使用指针交换,
因为对地址的操作实际上进行的是整数运算,比如:两个地址相减得到一个整数,表示两个变量在内存中的储存位置隔了多少个字节;地址和一个整数相加即“a+10”表示以a为基地址的在a后10个a类数据单元的地址。所以理论上可以通过和算术算法类似的运算来完成地址的交换,从而达到交换变量的目的。即:
int *a,*b;
*a=new int(10);
*b=new int(20); //a=0,b=0
a=(int*)(b-a); //a=0,b=0
b=(int*)(b-a); //a=0,b=0
a=(int*)(b+int(a)); //a=0,b=0
通过以上运算a、b的地址真的已经完成了交换,且a指向了原先b指向的值,b指向原先a指向的值了吗?上面的代码可以通过编译,但是执行结果却令人匪夷所思!原因何在?
首先必须了解,操作系统把内存分为几个区域:系统代码/数据区、应用程序代码/数据区、堆栈区、全局
您可能关注的文档
最近下载
- 某公司完整版审批权限表.doc VIP
- 2025浙江杭州青山湖科技城投资集团有限公司下属子公司招聘11人考试模拟试题及答案解析.docx VIP
- 马自达-马自达6阿特兹-产品使用说明书-马自达6阿特兹 2.5L蓝天尊崇版-CA7250ATE4-MAZDA6ATENZA用户手册.pdf VIP
- 泡泡玛特简介.pptx VIP
- 马勒第一交响曲(钢琴版)第3乐章.pdf VIP
- 西门子断路器3WL操作手册.pdf
- 《产业园区投建营数字化平台建设指南》.pdf VIP
- 00015 《英语(二)》高频 100 题.doc VIP
- 2024年一建管理真题完整.docx VIP
- 中医面诊知识培训课件.pptx VIP
文档评论(0)