今天动手写了个快速排序:
#include
typedef int (*data_compare)(int a, int b);
void swap(int *a, int *b)
{
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
int cmp_int(int a, int b)
{
return a - b;
}
int cmp_int_invert(int a, int b)
{
return b - a;
}
int partition(int *a, int left, int right, data_compare cmp)
{
int i;
int index = left;
int pivot = a[index];
swap(&a[index], &a[right]);
for (i = left; i < right; i++) {
if (cmp(a[i], pivot) < 0) {
swap(&a[index], &a[i]);
index++;
}
}
swap(&a[index], &a[right]);
return index;
}
void quick_sort(int *a, int left, int right, data_compare cmp)
{
int index;
if (left >= right)
return;
index = partition(a, left, right, cmp);
quick_sort(a, left, index - 1, cmp);
quick_sort(a, index + 1, right, cmp);
}
int main(void)
{
int i;
int a[10] = {3, 8, 5, 4, 9, 7, 1, 6, 2, 0};
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
quick_sort(a, 0, 9, cmp_int);
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
运行时发现结果不对:
3 8 5 4 9 7 1 6 2 0
0 1 2 3 0 0 0 0 0 0
怎么数据都变成0了.后面调试了半天,才发现是swap实现有问题.
对于void swap(int *a, int *b),功能很明显,交换指针a和b指向的值。实现的时候有多种方式:
void swap(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
当然我们也可以使用其他方式实现,不使用中间变量,而使用异或的方式,因为两个相同的数异或为零,如下所示:
void swap(int *a, int *b)
{
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
上面的方式咋一看好像没什么问题,但是当a = b时,即交换同一个指针指向的值时,由于*a ^ *b = 0,a指针指向的值为变成0.
因此在partition函数时,left编号的元素与pivot比较时,若条件成立,需要与编号index的元素交换,此时left = index,因此在调用swap时,a[index] = a[left] = 0.
可对上面的swap函数修改下,交换前进行判断,若相同则不用交换,不仅可以消除bug,同时可提高一定的效率:
void swap(int *a, int *b)
{
if (*a != *b) {
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
}