快速排序的稳定性分析

  • Post author:
  • Post category:其他

    快速排序是一个不稳定的排序算法,本文将着重分析该算法不稳定的原因所在。

    首先,考虑下图中对一个关键字都为 1 的序列所进行的交换操作。

     

     

      如图,交换前,枢纽元已放置在最后一个位置。图中,当遇到和枢纽元大小相同的元素时,游标 i 选择继续前进直到与游标 j 相遇为止,然后将枢纽元与游标  i  和 j 所指向的元素交换, 再递归的对左右两边的数组进行快速排序,这是快速排序的思想。

     但问题也出现了。如图,一轮递归结束后,左右两边的数组明显失衡,可想而知,左边数组仅仅是一个长度与当前数组相当的子数组,右边的数组长度为1,递归算法的复杂度将上升为 \small O\left ( N^2 \right ) ,这触犯了快速排序的 “大忌” !

     程序恶化的原因: 当游标所指向的元素同枢纽元相等时选择了继续前进,而不是停留在原地,这就导致游标肆无忌惮的一路向前,根本没有顾及到左右两个数组是否均衡,因而触犯了“大忌”。

     避免踩坑: 当游标所指向的元素同枢纽元相等时,待在原地不动,左右游标指向的元素进行交换,再各自向前移动。

     下图是没有踩坑的操作示意。

      

     

     据图,我们似乎做了很多没有必要的交换。但这样做使得最终的枢纽元出现在数组的中间位置上,左右数组呈均衡状态,理论上时间复杂度将是 \small O\left ( Nlog\left ( N \right ) \right ),快速排序的性能是最优的,避免了我们陷入复杂度为 \small O\left ( N^2 \right ) 的坑。

     本文的例子在实际当中很少出现,但当一个序列中存在大量重复的元素,此时如果选择游标继续前进的策略,无疑也会陷入性能上的低谷。

 

    结论: 根据上面的讨论,快速排序出于性能上的考虑,牺牲了算法的稳定性。虽然可以改变交换规则,使得算法保持稳定性,但却牺牲了性能,对于一个排序算法而言,这是得不偿失的,除非是上下文有稳定性方面的需求,否则,不建议改变交换规则。


版权声明:本文为gaoxueyi551原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。