a = a ^ b;
b = b ^ a;
a = a ^ b;
实现数据的交换。但是在快速排序的时候这个方法一下子失灵了。
#include <iostream>
using namespace std;
int QuickPartation(int vec[], int low, int high) {
if(low < high) {
int i = low - 1;
int temp = vec[high];
for(int j=low; j<=high-1; j++) {
if(vec[j] <= temp) {
i = i + 1;
vec[i] = vec[i] ^ vec[j];
vec[j] = vec[j] ^ vec[i];
vec[i] = vec[i] ^ vec[j];
}
}
vec[high] = vec[i+1];
vec[i+1] = temp;
return i+1;
}
}
void QuickSort(int vec[], int low, int high) {
if(low < high) {
int mid = QuickPartation(vec,low,high);
QuickSort(vec,low,mid-1);
QuickSort(vec,mid+1, high);
}
}
void Print(int vec[], int n) {
for(int i=0; i<n; i++)
cout<<vec[i]<<' ';
cout<<endl;
}
int main() {
int a[] = {12,4,5,8,21,1,13};
Print(a,7);
QuickSort(a,0,6);
Print(a,7);
system("pause");
return 0;
}
在上述自认为没有错误的程序上,程序的运行结果让我很纠结:
经过短暂分析可能是交换出的问题,于是我就采用比较传统的方式进行交换。
#include <iostream>
using namespace std;
int QuickPartation(int vec[], int low, int high) {
if(low < high) {
int i = low - 1;
int temp = vec[high];
for(int j=low; j<=high-1; j++) {
if(vec[j] <= temp) {
i = i + 1;
int m = vec[i];
vec[i] = vec[j];
vec[j] = m;
}
}
vec[high] = vec[i+1];
vec[i+1] = temp;
return i+1;
}
}
void QuickSort(int vec[], int low, int high) {
if(low < high) {
int mid = QuickPartation(vec,low,high);
QuickSort(vec,low,mid-1);
QuickSort(vec,mid+1, high);
}
}
void Print(int vec[], int n) {
for(int i=0; i<n; i++)
cout<<vec[i]<<' ';
cout<<endl;
}
int main() {
int a[] = {12,4,5,8,21,1,13};
Print(a,7);
QuickSort(a,0,6);
Print(a,7);
system("pause");
return 0;
}
运行结果表明问题就是出在数据交换上。
问题到底出在哪里?
经过观察数据可以发现在出错的数据排序过程中,被交换过的数据都被清0了,我们都知道,两个相同的数经过异或运算后会被清零,也就是说上面的数据都是由于相同的数进行异或导致的。难道“采用异或交换数据还有什么特殊情况?”
异或交换是一种通用的数据交换方式,没有什么特殊情况,只能是程序中的问题,经过分析程序,可以发现数据的情况为:
if(vec[0] < 13)
{
i = 0;
vec[0] = vec[0] ^ vec[0];
vec[0] = vec[0] ^ vec[0];
vec[0] = vec[0] ^ vec[0];
}
看到上面程序的过程中,其实会出现 i = j ,数据自己跟自己进行交换的情况,执行vec[0] =vec[0] ^ vec[0] 语句,会把vec[0] 中存储的数值变为0,即便是后面再运算,vec[0]的数值仍然为零,因为整体上就是一个数字进行异或。所以才会出现使用异或进行交换数据出现清零的情况。
因此如果采用异或进行数据交换时一定注意如果是引用传值(或者指针)的相同变量就不可以这样操作。总之,两个操作数内存地址不能相同。如果两个数的内存地址相同,说明两个数本来就相等,也没有必要进行数据交换,因此,在数据交换的过程中最好增加数据是否相等的判断。
经过以上分析可以对代码进行适当修改:
int QuickSortPartation(int a[],int low,int high) {
if(low < high) {
int i = low - 1;
int temp = a[high];
for(int j=low;j<high;j++) {
if(a[j] < temp) {
i++;
if( i != j){
a[i] = a[i] ^ a[j];
a[j] = a[j] ^ a[i];
a[i] = a[i] ^ a[j];
}
}
}
a[high] = a[i+1];
a[i+1] = temp;
return i+1;
}
}
上述代码运行之后的执行结果就正确了。
因此,在使用异或进行数据交换的过程中,一定要求交换两个数据的内存地址不同。