@清晰掉 swap函数

swap函数估计是一个各种各样程序都会频繁用到的子程序,可是你知道它究竟有多少种不同的写法吗?下面我就列举我知道的几种swap函数来跟大家分享一下。

(1)经典型---嫁衣法

无论是写程序还是干其他事情,一旦涉及到交换,就总是会遇到第三方。这个第三方可能是公正的监督者,也可能是一个徒为他人做嫁衣的可怜虫。在经典法的交换程序中,我们就需要有一个可怜虫来为我们提供暂时的服务。程序如下:

void swap(int *a,int *b)
{
int temp;

temp=*a;

*a=*b;

*b=temp;

}

我们看到,我必须用一个temp变量作为过渡,让他先拥有然后又再赋值给其他人。可见他也不是徒做嫁衣,而是先索取后奉献的主人公精神。哈哈,扯远了。

(2)经典型改进版---范型法
上面的那个swap函数只能交换int类型变量,如果我想交换double类型,short类型,char类型......呢?上面的程序就必须重新写,可是又不是完全推倒重来,只需要修改相应的类型变量就可以了,如果是用C++来编程,我们还可以用到NB的模板,可是C语言就没有这种特点了。唯一可以用的便是void*指针。void*指针可以视为一种通用指针,任何指针都可以转换为void*指针而不会丢失值。同理,只要我们把原先的指针变量换成void*类型不就行了。可是,你很快发现,这样不行。为什么呢?因为我们没有通用的嫁衣。C语言中的变量不可以为void类型,也就是说没有void temp; 这种古怪的东西。那怎么办呢?我们可以从底层去想两个数交换的本质。不就是相应的内存值交换嘛。我们可以联想到memcpy函数,我们可以模仿着来,写一个函数,通过传入void*指针和变量类型的字节大小,来将这两个变量相应的字节内容发生对换。程序如下:

void swap(void *a,void *b,size_t size)
{

unsigned char *p1=(unsigned char *)a;          //强制类型转换

unsigned char *p2=(unsigned char *)b;

Unsigned char temp;                         //字节型的嫁衣

while(size--)

{

temp=*p1;

*p1=*p2;

*p2=temp;

p1++;

p2++;

}

}

使用的时候可以这样调用:swap( &a,&b,sizeof(int) );
这种字节的分别交换可以通用各种类型的交换,当然,彼此之间应该是同种类型,否则会因为类型大小,字节序等一些问题发生错误。

(3)取巧型---赋值法
这个方法其实一个很取巧的方法,大家先看一下程序,看能不能看出巧在哪里:
void swap(int *a,int *b)
{
*a=*a+*b;

*b=*a-*b;

*a=*a-*b;

}
这种方法有一个好处,那就是不用消耗额外的变量空间,只需要两个变量做一些运算即可。让我们慢慢看:
首先:

我用A代表a+b

A=a+b,            这时候A的值为两者之和

接着,b=A-b, 也就是b=A-b=a+b-b=a,这时候b得到了a的值
最后,a=A-b, 因为经过上面的运算,b=a,所以a=A-b=a+b-a=b,这时候a得到了b的值。
所以,交换成功了。

(4)诡异型---逻辑运算法
如果没有仔细拿纸算一算的话,这段程序估计会晕倒很多人,让我们来看一下吧:
void swap(int *a,int *b)
{

//  *a^=*b^=*a^=*b;  这种做法达不到效果,不知道为什么

*a=*a^*b;
*b=*b^*a;
*a=*a^*b;

}
怎么样,够诡异的吧。如果我们把它拆开来看的话,其实也没那么可怕:
首先我们必须明确运算顺序,是从右至左:
*a=*a^*b;
*b=*b^*a;
*a=*a^*b;
在解释这段代码的时候,我们先普及一下逻辑运算的基础知识,^ 符号是异或符号,也就是如果两个逻辑变量各不相同,其表达式值为1,反之为0 。则有:

A^A=0

A^1=~A
A^0=A
A^B^C=A^(B^C)=B^(A^C)

首先,A=a^b;

接着,b=b^A=b^a^b=a^0=a,这时候b获得了a的值。
最后,a=A^b=a^b^a=b^0=b,这时候a获得了b的值。

时间: 2025-01-01 22:45:15

@清晰掉 swap函数的相关文章

《Effective C 》资源管理:条款25--考虑写出一个不抛出异常的swap函数

条款25考虑写出一个不抛出异常的swap函数 条款25:考虑写出一个不抛出异常的swap函数 swap是STL中的标准函数,用于交换两个对象的数值.后来swap成为异常安全编程(exception-safe programming,条款29)的脊柱,也是实现自我赋值(条款11)的一个常见机制.swap的实现如下: namespace std{ template<typename T> void swap(T& a, T& b) { T temp(a); a=b; b=temp;

swap函数的例子

13.31为你的HasPtr类定义一个<运算符,并定义一个HasPtr的vector为这个vector添加一些元素,并对它执行sort.注意何时会调用swap. #include<iostream> #include<string> #include<new> #include<vector> #include<algorithm> using namespace std; class HasPtr { friend void swap(H

条款25:考虑写出一个不抛异常的swap函数

条款25:考虑写出一个不抛异常的swap函数 swap函数在C++中是一个非常重要的函数,但实现也非常复杂. 看一个缺省的std::swap函数的实现 namespace std { template<typename T> void swap( T& a , T& b) { T temp(a); a = b; b = temp } } ①内置类型的调用 int a = 2; int b =3; std::swap(a, b); cout<<"a:&quo

作业二、comp和swap函数

一.swap函数的代码及运行情况 1.代码 1 #include<stdio.h> 2 int main() 3 { 4 void swap(int *m,int *n); 5 int a,b; 6 int *p1,*p2; 7 scanf("%d,%d",&a,&b); 8 p1=&a; 9 p2=&b; 10 swap(p1,p2); 11 printf("%d,%d\n",*p1,*p2); 12 return 0;

关于swap函数传值的问题

#include <stdio.h> void swap(int * p3,int * p4); int main() {  int a = 9;  int b = 8;  int * p1 = &a;  int * p2 = &b;    printf("%x %x\n",p1,p2);  swap(p1,p2);    printf("%d %d\n",a,b);  printf("%d %d\n",*p1,*p2

c/c++和java实现swap函数的不同处

首先我们来看一下在c/c++中实现的swap函数 void swap ( int & a, int & b) { int Temp; temp = a; a = b; b = temp; } 那么在java中是否还能这样呢,很显然java中没有地址引用符号了. 首先我们来看下c/c++和java的区别. 本质区别 C/C++中swap功能的本质:通过传递变量地址(指针或引用)来交换变量地址中的值. Java标榜其中对C/C++一个很大的改进就是:Java对程序员屏蔽了变量地址的概念,减少指

C语言形参与实参的概念及swap函数

形式参数(formal argument)和实际参数(actual argument)是什么? void function(int n); //n为形式参数 int main { int times=5; function(times); //times为实际参数 } void function(int n) { for(int i=0;i<n;i++) printf("hello\n"); } 在声明一个参数时就创建了一个叫形式参数的变量,在上面的例子中形式参数是叫做n的变量.

Effective C++ Item 25 考虑写出一个不抛异常的swap函数

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛出异常 示例: stl里的swap算法 namespace std{ template<typename T> void swap(T &a, T &b){ T temp(a); a = b; b = temp; } } //"pimpl手法"(pointer

Effective C++ 条款25 考虑写出一个不抛出异常的swap函数

1. swap是STL的一部分,后来成为异常安全性编程(exception-safe programming)(见条款29)的一个重要脊柱,标准库的swap函数模板定义类似以下: namespace std{ template<typename T> swap(T& lhs,T& rhs){ T temp(lhs); lhs=rhs; rhs=temp; } } 只要T类型支持拷贝构造以及拷贝赋值,标准库swap函数就会调用T的拷贝构造函数和拷贝构造操作符完成值的转换,但对于某