我们在实现交换的时候一般都是用一个中间变量来暂存:
void swap(int& a, int& b) {
int temp = a; //exchange
a = b;
b = temp;
}
类似于这样,然而也有不用中间变量的方法:
void swap(int& a, int& b) {
a += b;
b = a - b;
a -= b;
}
还有这样:
void swap(int& a, int& b) {
a = a^b;
b = a^b;
a = a^b;
}
这种取巧的方法相信大家都见过,可是,他们是有缺陷的!
是的,我被坑了,在今天手写了个快排,需要随机选一个数和第一个元素交换,一开始是用的异或交换,结果输出错误:
后面发现似乎是swap的问题,然后写了三个swap来测试:
#include<iostream>
#include<ctime>
#include<stdlib.h>
using namespace std;
void swap2(int& a, int& b) {
a = a^b;
b = a^b;
a = a^b;
}
void swap1(int& a, int& b) {
int temp = a; //exchange
a = b;
b = temp;
}
void swap3(int& a, int& b) {
a += b;
b = a - b;
a -= b;
}
void quicksort(int* a, int left, int right) {
if (left < right) {
int ra = left + (right - left + 1)*rand() / (RAND_MAX + 1);
swap1(a[left], a[ra]);
int x = a[left];
int l = left;
int r = right;
while (true) {
while (l < r&&a[r] >= x)
r--;
if (l < r)
a[l++] = a[r];
while (l < r&&a[l] < x)
l++;
if (l < r)
a[r--] = a[l];
if (l >= r)
break;
}
a[l] = x;
quicksort(a, r + 1, right);
quicksort(a, left, r - 1);
}
}
int main() {
int a[] = { 3,1,2,0,7,5,6,9,4,8 };
srand(time(0));
quicksort(a, 0, sizeof(a) / sizeof(int) - 1);
for (int i = 0; i < sizeof(a) / sizeof(int); i++)
printf("%d\t", a[i]);
cin.get();
return 0;
}
swap1的结果是正确的:
而swap3也错了:
注意到都是多了0元素。后面经过我的探究发现了问题所在!
就是这种交换不能和自己本身交换!
就是这种交换不能和自己本身交换!
就是这种交换不能和自己本身交换!
重要的话说三遍。当和本身交换时,他的值会为零!在分治方法中最好不要使用这种交换,因为他可能会分到最后为一个元素和它本身交换。其实最好使用swap1虽然可能增加了消耗,但是程序bug会更少。