zoukankan      html  css  js  c++  java
  • @清晰掉 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,反之为。则有:

    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的值。

  • 相关阅读:
    模板 无源汇上下界可行流 loj115
    ICPC2018JiaozuoE Resistors in Parallel 高精度 数论
    hdu 2255 奔小康赚大钱 最佳匹配 KM算法
    ICPC2018Beijing 现场赛D Frog and Portal 构造
    codeforce 1175E Minimal Segment Cover ST表 倍增思想
    ICPC2018Jiaozuo 现场赛H Can You Solve the Harder Problem? 后缀数组 树上差分 ST表 口胡题解
    luogu P1966 火柴排队 树状数组 逆序对 离散化
    luogu P1970 花匠 贪心
    luogu P1967 货车运输 最大生成树 倍增LCA
    luogu P1315 观光公交 贪心
  • 原文地址:https://www.cnblogs.com/ysdu/p/4846579.html
Copyright © 2011-2022 走看看