小言_互联网的博客

高频面试题-如何交换两个变量值?办法没你想得那么多!

356人阅读  评论(0)

​来源:公众号【编程珠玑】

作者:守望先生

ID:shouwangxiansheng

 

C语言交换两个整型变量,你有哪些方法?那么多方法,又有哪几个可行?

不可行的方法

初学者最容易理解错的方法:


  
  1. //来源:公众号【编程珠玑】
  2. //https://www.yanbinghu.com
  3. #include<stdio.h>
  4. void swap(int a,int b)
  5. {
  6.      int temp = a;
  7.     a = b;
  8.     b = temp;
  9. }
  10. int main(void)
  11. {
  12.      int a =  10;
  13.      int b =  24;
  14.     swap(a,b);
  15.      //输出a = 10,b = 20
  16.      printf( "a = %d,b = %d\n",a,b);
  17.      return  0;
  18. }

不理解为何不行的请参考《传值与传指针》。

理解实参只是原数据的一个拷贝,非常关键。

可行方法

这里最容易想到的一种方法:


  
  1. //来源:公众号【编程珠玑】
  2. //https://www.yanbinghu.com
  3. #include<stdio.h>
  4. void swap(int *a,int *b)
  5. {
  6.      int temp = *a;
  7.     *a = *b;
  8.     *b = temp;
  9. }
  10. int main(void)
  11. {
  12.      int a =  10;
  13.      int b =  24;
  14.     swap(&a,&b);
  15.      //输出a = 24,b = 10 
  16.      printf( "a = %d,b = %d\n",a,b);
  17.      return  0;
  18. }

但是有人还试图用类似的方法交换字符串,那就不可取了:


  
  1. //来源:公众号【编程珠玑】
  2. //https://www.yanbinghu.com
  3. #include<stdio.h>
  4. void swap(char *a,char *b)
  5. {
  6.      char *temp = a;
  7.     a = b;
  8.     b = temp;
  9. }
  10. int main(void)
  11. {
  12.      char a[] =  "hello";
  13.      char b[] =  "world";
  14.     swap(a,b);
  15.      //输出a = hello,b = world
  16.      printf( "a = %s,b = %s\n",a,b);
  17.      return  0;
  18. }

什么?为什么没有像你预期那样交换a和b的内容?还是参考《传值与传指针》。

不借助临时变量一


  
  1. //来源:公众号【编程珠玑】
  2. //https://www.yanbinghu.com
  3. #include<stdio.h>
  4. void swap(int *a,int *b)
  5. {
  6.     *a = *a + *b;  //10 + 24 = 34 ,有溢出的风险
  7.     *b = *a - *b;  //34 - 24 = 10
  8.     *a = *a - *b;  //34 - 10 = 24
  9.      //变体如下:
  10.      //*a = (*a + *b) - (*b = *a);
  11. }

不过这个方法的缺点非常明显,那就是存在溢出的风险。

还有下面这种类似的方法:


  
  1. void swap(int *a,int *b)
  2. {
  3.     *a = *a * *b;
  4.     *b = *a / *b;
  5.     *a = *a / *b;
  6. }

这种方法除了有溢出风险外,b还不能为0。

不借助临时变量二


  
  1. void swap(int *a,int *b)
  2. {
  3.     *a = *a ^ *b;
  4.     *b = *a ^ *b;
  5.     *a = *a ^ *b;
  6.      //变体如下
  7.      //*a = (*a ^ *b) ^ (*b ^ *a);
  8. }

没错,就是采用异或,相同异或(0^0=0;1^1=0)结果为0,不同异或(0^1 = 1)结果为1。

*a = *a ^ *b:

0 1 0 1 0 a = 10
1 1 0 0 0 b = 24
1 0 0 1 0 a = a ^ b = 18

*b = *a ^ *b:

1 0 0 1 0 a = 18
1 1 0 0 0 b = 24
0 1 0 1 0 b = a ^ b = 10

*a = *a ^ *b:

1 0 0 1 0 a = 18
0 1 0 1 0 b = 10
1 1 0 0 0 a = a ^ b = 24

不过这种方法中,如果传入参数指向同一地址,它并不如预期那样工作:


  
  1. //来源:公众号【编程珠玑】
  2. //https://www.yanbinghu.com
  3. #include<stdio.h>
  4. void swap(int *a,int *b)
  5. {
  6.     *a = *a ^ *b;
  7.     *b = *a ^ *b;
  8.     *a = *a ^ *b;
  9. }
  10. int main(void)
  11. {
  12.      int a =  10;
  13.     swap(&a,&a); //都传入a
  14.      //输出a = 0
  15.      printf( "a = %d\n",a);
  16.      return  0;
  17. }

至于前面提到的不借助第三个变量的方法,你都可以尝试一下,它可能不如你预期那样工作奥!

既然如此,可以稍微改进一下:


  
  1. void swap(int *a,int *b)
  2. {
  3.      if(a != b)
  4.     {
  5.         *a = *a ^ *b;
  6.         *b = *a ^ *b;
  7.         *a = *a ^ *b;
  8.     }
  9. }

总结

那么问题来了,那种方式更快呢?

答案可能让你意外:
在编译器的优化下,使用临时变量的方式可能是最快的。

你还有什么方法交换两个整数的值?欢迎留言。


  
  1. #include<iostream>
  2. int main()
  3. {
  4.      std:: string a =  "10";
  5.      std:: string b =  "24";
  6.      std::swap(a,b);
  7.      std:: cout<< "a="<<a<< ";b="<<b<< std:: endl;
  8.      return  0;
  9. }

转载:https://blog.csdn.net/hyb612/article/details/103940306
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场