交换算法引起的快速排序错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了交换算法引起的快速排序错误相关的知识,希望对你有一定的参考价值。

前两天手写快速排序,最后得到的结果是错误的而且还错的非常奇怪。输入的待排序数组是:

int a[10] = {2,6,4,8,0,1,5,9,3,7};

最后得到的结果是:

0 0 2 0 0 0 6 0 8 0

上网看了看别人的代码,发现我写的快速排序的算法逻辑是没有错误的,难道是交换元素时用的算法不对?

我用的交换算法是异或交换,就是不用中间变量那种:

void swap( int *a, int *b )
{
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
}

然后将其换成使用中间变量的交换算法:

void swap( int *a, int *b )
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

然后结果就对了,但是一直想不明白为什么。最后通过在纸上演算一遍才恍然大悟。

例如我这个输入:

2 6 4 8 0 1 5 9 3 7

中间的比较交换过程略去不表,然后它会到达这么一个状态:

0 /1 / 2 / 8 4 6 5 9 3 7
^
^

解释一下,第一轮排序将2放到属于它的位置,然后分成左边的序列0 1和右边的序列8 4 6 5 9 3 7。第二轮对左边的0 1进行排序,将0放置到属于它的位置(没动)。第三轮对1进行排序,问题就出在这里,由于只有一个元素,但按照算法也要进行一次交换,如果使用不借助中间变量的交换算法(加减法、异或法),传递给void swap( int *a, int *b )的a, b指向的是同一地址,也就是说实际上是这样的:

void swap( int *a, int *a )
{
    *a = *a + *a;
    *a = *a - *a; //*a==0,永世不得翻身
    *a = *a - *a;
}

其实在第二轮时,0与0交换就出现了这个问题,但是由于它是0没有表现出来。

 

以前总觉得不用中间变量的交换算法稍微有那么点帅,看来还是得想好了再用。可靠性最重要啊。

以上是关于交换算法引起的快速排序错误的主要内容,如果未能解决你的问题,请参考以下文章

算法交换排序——快速排序+冒泡排序

java代码[No.4]—快速排序算法的三种方式及其优化

排序算法(冒泡排序选择排序插入排序快速排序归并排序)

排序算法(冒泡排序选择排序插入排序快速排序归并排序)

排序算法(冒泡排序选择排序插入排序快速排序归并排序)

常见排序算法详解(冒泡选择插入快速希尔归并)