临时变量

通过建立一个临时变量来实现两数交换:

def swap(x, y):
    print(x, y)
    tmp = x
    x = y
    y = tmp
    print(x, y)
    return x, y

if __name__ == '__main__':
    swap(1, 2)

缺点:

需要消耗额外的内存。

优点:

不限制类型,大多数类型都能使用该操作。


加减交换

通过加减法实现:

def swap(x, y):
    print(x, y)
    x = x + y
    y = x - y
    x = x - y
    print(x, y)
    return x, y

if __name__ == '__main__':
    swap(1, 2)

假设两个数保存在x和y中:

  1. 先将y中的值加到x中。

    即这两个数一同保存在同一内存空间x中。

  2. 然后用x的值减去y的值,再将其保存到内存y中。

    x-y即为x最初的值。

  3. 最后再用x的值减去y的值,赋给内存x。

    x最初的值已经在y中,所以x-y的值为y最初的值。

缺点:

该方法只适用于数值不大的数,如果数值过大,可能会越界(对于某些语言来说)。


异或交换

通过异或的操作实现:

def swap(x, y):
    print(x, y)
    x = x ^ y
    y = x ^ y
    x = x ^ y
    print(x, y)
    return x, y

if __name__ == '__main__':
    swap(1, 2)

这个算法使用了按位异或的性质。假设x变量上的值为X,y变量上的值为Y。

  1. 首先,第一次异或操作得到了掩码M。M记录了X和Y两个二进制值中相等位和不相等位的信息。

    例如:

    x =         0110 1011
    y =         1100 0010
    x = x ^ y = 1010 1001   # 得到了掩码M,M记录了两个数中相等的位和不相等的位
    
  2. 然后,通过掩码M与要交换的其中一个值进行异或,就可以复原得到另外一个值。

    例如,掩码M被存储在x中,那么将x和y进行异或,就可以复原出X。

    y = x ^ y = 0110 1011   # 通过M与Y按位异或可以复原出X
    
  3. 最后一次异或,其原理同上。

    例如,将x和y再次进行异或,也就是两数差异位信息和X进行异或,就可以得到Y。

    x = x ^ y = 1100 0010   # 同理,再次异或后可以复原出Y
    

这种方式是利用了按位异或的 “切换” 性质。按位异或会根据掩码中为1的位对另一个操作数进行切换(将1变成0,将0变成1)。

$$ \begin{array}{lll} & 1100 & 0010 & = Y \\ \oplus & 1010 & 1001 & = M \\ \hline & \textcolor{red}{\underline 0} 1 \textcolor{red}{\underline 1} 0 & \textcolor{red}{\underline 1} 01 \textcolor{red}{\underline 1} & = X \end{array} $$

缺点:

只能对整数类型执行位操作,不能对实数类型进行位操作。