程序中关于数据交换的讨论

      数据交换或许是程序中经常遇到的一类最为基本的操作,今天讨论的问题是关于就是在写程序时碰到的问题,一直以来自己交换数据都采用下列方式实现:
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;
	}
}

上述代码运行之后的执行结果就正确了。

因此,在使用异或进行数据交换的过程中,一定要求交换两个数据的内存地址不同。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值