如标题所述,这该是一个再明显不过的常识:谁都知道,两个相同的数异或为0。当然,在考察一个异或知识的时候,基本都不会出错。但是当我们在其他场合使用异或来辅助其他实现的时候,脱离了那个单一的知识点的语境,却容易掉入陷阱当中。这可能也是因为自己学的时候都把注意力放在单纯的记忆上,而没有挖掘多样化的使用场合以活学活用的缘故。所以,今天在试着写堆排序时花了一小时发现这个无知的错误之后,是很让我感觉吃惊的。
代码如下:
1 #include <stdio.h> 2 3 void Swap(int *a, int *b) 4 { 5 *a = *a ^ *b; 6 *b = *a ^ *b; 7 *a = *a ^ *b; 8 9 return ; 10 } 11 void SiftUp(int *arr, int n) 12 { 13 int current, parent; 14 15 current = n; 16 parent = n/2; 17 18 while (parent >= 1) 19 { 20 if (arr[parent] <= arr[current]) 21 break; 22 23 Swap(&arr[parent], &arr[current]); 24 25 current = parent; 26 parent /= 2; 27 } 28 29 return ; 30 } 31 32 void SiftDown(int *arr, int n) 33 { 34 int current, son; 35 36 current = 1; 37 son = current * 2; 38 39 while (son <= n) 40 { 41 if (((son+1)<=n) && (arr[son]>arr[son+1])) 42 son += 1; 43 44 if (arr[current] <= arr[son]) 45 break; 46 47 Swap(&arr[son], &arr[current]); 48 current = son; 49 son *= 2; 50 } 51 52 return ; 53 } 54 55 void Print(int *arr, int n) 56 { 57 int i; 58 59 for (i=1; i<=n; i++) 60 printf("%d ", arr[i]); 61 printf("\n"); 62 } 63 64 #define TST_NUM 7 65 int main() 66 { 67 int i; 68 int tstData[TST_NUM + 1] = {0, 9, 1, 19, 2, 7, 5, 3}; 69 70 for (i=1; i<=TST_NUM; i++) 71 { 72 SiftUp(tstData, i); 73 } 74 Print(tstData, TST_NUM); 75 76 for (i=TST_NUM; i>=1; i--) 77 { 78 SiftDown(tstData, i); 79 Swap(&tstData[1], &tstData[i]); 80 } 81 Print(tstData, TST_NUM); 82 83 return 0; 84 }
堆排序当中会反复的交换数组中两个元素,为了显得不一般,我特意使用了异或操作来实现两个数的对换。但输出结果发现在下滤操作的最后一步,即同一个数进行对换时最后的值为0,这时才猛然想起其原因。
brainking tst:)./heapSortTst 1 2 3 9 7 19 5 0 9 7 5 3 2 1
其实,这样一个小错误来篇总结进行详述显得大费周折。但往往就是一些小的错误才让自己反思,为什么看似掌握了很多的知识点但是在使用的时候还是和没有学一样。这次这个小错误,之所以用异或也是知道其两数相同异或为0的这种性质才能实现两数直接对换,讽刺的是,在另一个语境当中使用时却是坏在了同样的性质之下。所以,这篇小结一是提醒自己知识点得在学习的时候要找机会去用,在实践当中进行理解;二是要提醒自己,这个小错误不能再换了,下次使用对换算法的时候一定要考虑周全。