交换两个数的值多种解法

来源:互联网 发布:360优化 大师官网下载 编辑:程序博客网 时间:2024/04/25 15:34

见到这道题,可能你会想到小时候玩过的游戏,将分别装有酱油和醋的两个瓶子交换,醋装到酱油瓶子里,酱油装到醋瓶子里,我们都知道,交换的过程需要家住一个空瓶子,当然,我们这道题也是同样的道理,需要创建一个临时变量来辅助交换。下面看具体的代码实现:


[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:24px;">#include<stdio.h>//程序中用到输出函数printf,所以需要引其对应的头文件  
  2. #include<stdlib.h>//system的头文件   
  3. int main()   
  4. {   
  5.   int a=3;  
  6.  int b=5;  
  7.  int tmp=0;//创建临时变量来辅助交换  
  8.    
  9.   tmp=a;  
  10.  a=b;  
  11.  b=tmp;  
  12.  printf("a=%d b=%d\n",a,b);  
  13.  system("pause");//使程序停下来,有的编译环境可能不需要  
  14.  return 0;  
  15.  }</span>  

程序写完了,让我们看下运行结果吧!

程序就是按照我们的思路,交换了a和b的值,这是为什么呢?我们来分析一下。

很好理解了吧,但是,我们最好封装一个函数,避免主函数内杂乱无章,在以后的编程中,也应该保持这种良好的编程习惯。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:24px;">#include<stdio.h>  
  2. #include<stdlib.h>  
  3. void swap(int x,int y)  
  4. {  
  5.    int tmp=x;  
  6.    x=y;  
  7.    y=tmp;  
  8. }  
  9. int main()  
  10. {  
  11.    int a=3;  
  12.    int b=5;  
  13.    swap(a,b);  
  14.    printf("a=%d  b=%d\n",a,b);  
  15.    system("pause");  
  16.    return 0;  
  17. }</span>  


再来看下运行结果:

咦,怎么封装了函数就错了呢?你知道什么原因吗?

同样的,我们可以用环境监视来说明这个问题。

a,b和x,y的值虽然一样,但其地址却不相同

调用swap函数后,x和y的值成功交换,而a,b的值没丝毫变化

通过这两幅图,我们可以清楚的看到形参只是实参的一份临时拷贝,二者在内存中的地址并不相同,这种传参方式成为传值调用,起不到我们预想的效果,我们可以进一步做下面的改进。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:24px;">#define _CRT_SECURE_NO_WARNINGS 1  
  2. #include<stdio.h>  
  3. #include<stdlib.h>  
  4. void swap(int *x,int *y)  
  5. {  
  6.    int *tmp=NULL;  
  7.    *tmp=*x;  
  8.    *x=*y;  
  9.    *y=*tmp;  
  10. }  
  11. int main()  
  12. {  
  13.    int a=3;  
  14.    int b=5;  
  15.   
  16.    swap(&a,&b);//传址调用  
  17.    printf("a=%d  b=%d\n",a,b);  
  18.    system("pause");  
  19.    return 0;  
  20. }</span>  
上面说传值调用达不到我们预想的效果,那有人可能会想到这种做法,那么结果如何呢?让我们拭目以待。



程序崩溃了,你很好奇为什么,其实你犯了一个天大的错误,待我给你细细道来。



这样就一清二楚了吧,以前我看过一个网上教程,总说一句“No pic you say a JB.”我总是理解不了什么意思,现在总算理解了,嘻嘻,此段话少儿不宜哦,好吧,说正事!错了这么多,这下总该对了吧。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:24px;">#include<stdio.h>  
  2. #include<stdlib.h>  
  3. void swap(int *x,int *y)  
  4. {  
  5.    int tmp=0;  
  6.    tmp=*x;  
  7.    *x=*y;  
  8.    *y=tmp;  
  9. }  
  10. int main()  
  11. {  
  12.    int a=3;  
  13.    int b=5;  
  14.   
  15.     swap(&a,&b);  
  16.    printf("a=%d  b=%d\n",a,b);  
  17.    system("pause");  
  18.    return 0;  
  19. }</span>  


看下结果:

目的是达到了,但是如果在面试过程中,面试官说不允许创建临时变量,那么你还会吗?

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:24px;">#include<stdio.h>  
  2. #include<stdlib.h>  
  3. void swap(int *x,int *y)  
  4. {  
  5.    *x=*x+*y;  
  6.    *y=*x-*y;  
  7.    *x=*x-*y;  
  8. }  
  9. int main()  
  10. {  
  11.    int a=3;  
  12.    int b=5;  
  13.   
  14.     swap(&a,&b);  
  15.    printf("a=%d  b=%d\n",a,b);  
  16.    system("pause");  
  17.    return 0;  
  18. }</span>  
结果:

鉴于这道题很简单,不封装函数可能看的更清楚,下面我们就直接在主函数中完成交换了,但是请务必记得,如果函数比较复杂,一定要用函数封装,看起来简洁明了,也保持了主函数的干净度,一种很好的编程习惯,不要忘记哦!

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:24px;">#include<stdio.h>  
  2. #include<stdlib.h>  
  3.   
  4. int main()  
  5. {  
  6.    int a=3;  
  7.    int b=5;  
  8.      
  9.    a=a+b;  
  10.    b=a-b;  
  11.    a=a-b;  
  12.   
  13.    printf("a=%d  b=%d\n",a,b);  
  14.    system("pause");  
  15.    return 0;  
  16. }</span>  


原理:


是的,通过我们思考之后,你会发现其实简单的加减法就可以帮我们搞定这件事,但是回过头想想,既然加减法可以,那么乘除法行不行呢?让我们试一试。



你有没有想到余数的问题呢,有人可能想如果除不尽,小数部分丢掉了不就达不到效果了吗?在这里,我先表扬你一下,想法很好,善于动脑才是好孩子嘛,对不对,但是,请看我们的代码。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:24px;">#include<stdio.h>  
  2. #include<stdlib.h>  
  3.   
  4. int main()  
  5. {  
  6.    int a=3;  
  7.    int b=5;  
  8.      
  9.    a=a*b;  
  10.    b=a/b;  
  11.    a=a/b;  
  12.   
  13.    printf("a=%d  b=%d\n",a,b);  
  14.    system("pause");  
  15.    return 0;  
  16. }</span>  



你会发现先做的是乘法,既然a保存的是它俩的公倍数,怎么可能除不尽呢,对吧!

再看看结果:

依然正确,但是,这两种做法有没有弊端呢?答案是肯定的,要不然我还说它干嘛,

比如我们其中一个数是0或者-1,会出现什么结果呢?

加减法输入-1:


咦,好着呢呀,所以你感觉没问题,那么你就大错特错了,我用的是VS2010,算是比较高版本的编译器吧,可能对程序进行了优化,让我们进入VC6.0再看看结果:


虽然没有语法错误,编译链接都可以通过,但是却执行不了,为什么呢,因为你的做法导致了数据溢出。

再看看乘除法输入0:

分析一下:

既然上面的两种方法都有相应的弊端,那么有没有一种更完美的办法呢,有人很聪明,想到了异或运算符,异或嘛,相异而或,相同为0,相异为1.

下面讲一下为什么它能克服上面的问题。

还有一种扩展方法,知道有这种方法即可,在此不做分析,有兴趣的自行研究

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:24px;">#include<stdio.h>  
  2. #include<stdlib.h>  
  3.   
  4. int main()  
  5. {  
  6.    int a=3;  
  7.    int b=5;  
  8.    int tmp=0;  
  9.      
  10.    tmp = a;  
  11.    a=((__int64)( (__int64) b<<32 | (a = b) ) >> 32);  
  12.    b=((__int64)( (__int64) tmp<<32 | (b = tmp) ) >> 32);  
  13.   
  14.   
  15.    printf("a=%d  b=%d\n",a,b);  
  16.    system("pause");  
  17.    return 0;  
  18. }</span>  


结果:


做到这里,这道题算是完美完成了,但是你还有兴趣的话,可以考虑下怎样交换不同类型的数,下面我们给出一种实现方法。

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:24px;">#include<stdio.h>  
  2. #include<stdlib.h>  
  3. #define TYPE float  
  4. #define SWAP(type,a,b){type tmp; tmp=a; a=b; b=tmp;}  
  5.   
  6. int main()  
  7. {  
  8.       
  9.     TYPE a=3.4;  
  10.     TYPE b=5.5;  
  11.   
  12.     SWAP(TYPE,a,b);  
  13.    printf("a=%f  b=%f\n",a,b);  
  14.    system("pause");  
  15.    return 0;  
  16. }</span>  


运行结果:

0 0
原创粉丝点击