一. 快速排序的基本思想
1.选定 pivot( 分区点 )
- 固定位置:最简单的方法是选择数组的第一个元素或最后一个元素作为分区点。这种方法 在某些情况下可能效果不错,但在某些特定的输入情况下(比如输入的数据集已经是有序或 近乎有序的时候)可能会导致算法的性能下降。
- 随机选择:随机选择一个元素作为分区点。这种方法可以减少特定输入情况下的性能下降 的可能性,但仍然可能出现不好的分区点选择。
- 三数取中:选择数组的第一个元素、中间元素和最后一个元素,并取它们的中间值作为分区 点。这种方法可以在大多数情况下得到一个相对较好的分区点,从而提高算法的性能。
- 随机化快速排序:在每次递归调用时,随机选择一个元素作为分区点。这种方法可以进一步 减少特定输入情况下的性能下降的可能性,并且通常具有较好的平均性能。
2.将数组中 大于 pivot 的放在 pivot 的右边
将数组中 小于 pivot 的放在 pivot 的左边
3.对左右子序列重复上述操作
二. 算法描述
就我个人而言,需要一个函数表示快速排序算法大致骨架。然后再定义一个分区函数,表示首先进行分区操作,定义变量 left 与 right ,用于指定当前待排数组的指定范围。然后定义快慢指针,其初始值均为left,fast 指针用于遍历待排子序列中的所有元素,slow 指针的作用是指示下一个分区点的元素。之后定义一个专门用于交换元素的函数。最后使用递归完成算法。
当 fast > right 时,fast 向前移动一位
当 fast < right 时,交换快慢指针,且二者同时向前移动一位
当 fast = right 时, 结束循环,交换 slow 与 right,此时 slow 指向的是临近的元素,分区点为递归做准备
三. 代码实现
四. 算法分析
该算法有两个难点:
1. 如何实现分区逻辑?
- 选择一个分区点(通常是最右边或最左边的元素),然后通过遍历数组,将小于分区点的元素放置在分区点的左边,大于分区点的元素放置在分区点的右边。最后,将分区点放置在正确的位置上。这个过程可以使用快慢指针来实现,通过交换元素并移动指针的方式进行操作。
2. 如何控制分区的次数? Tip:其背后就是数据结构的二叉树,也就是遍历二叉树中所有的节点
- 在每次分区操作后,分区点所在的位置已经是正确的,即分区点左边的元素都小于等于它,右边的元素都大于等于它。然后,分别对分区点左边和右边的子数组进行递归调用,继续进行分区操作,直到子数组的大小为1或0时停止递归。
五. 改进算法(个人意见)
若出现元素与分区点 pivot 值相等的情况,计算机会如何处理?在数据足够大的情况下会处理大量重复的元素。
改进的算法通过将数组划分为三个部分:小于分区点、等于分区点和大于分区点。它的基本思想是选择一个分区点,然后通过遍历数组,将小于分区点的元素放置在左侧,等于分区点的元素放置在中间,大于分区点的元素放置在右侧。然后,对左侧和右侧的子数组进行递归调用,继续进行三路分区操作。
这减少了不必要的的元素交换和递归调用次数,可以更好的处理大量重复元素的情况