快速排序
快速排序的思想
快速排序通过一次排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。具体步骤如下:
- 从数列中挑出一个元素,称为"基准"(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区操作;
- 递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。
图解快速排序
这里展示放置第一个基准的过程,首先选择第一个数字作为基准。
接下来我们在26和20的位置分别设置两个指针low和high,并用maddle来存储基准的值(使得列表中基准的位置可以用于元素替换)
现在我们的目的是让小的数字在前面,大的数字在后面,鉴于我们现在在第一个基准的位置可以用于元素的替换(此处可以看作为空),所以我们从high指针开始进行操作(遍历向前直到找到比基准小的数字)。
此时我们可以知道high的位置为空,也就是说high的位置可以用作下一个元素的存储位置,因此此时我们转换到操作low指针,通过low指针找到比基准54大的元素。
和上面同样的原理,我们再继续操作high指针(这里展示剩下交换的过程,如果理解交换过程可以跳过)
最后如果我们再把指针进行左移操作,就会使得low和high指针重合,此时重合的位置也就是我们最开始找到的基准(54)的位置,至此,我们就可以把基准(54)放到该位置上了。
此时我们会发现在54前面的数字都比54小,后面的数字都比54大,这也就证明我们已经找好了54的位置,后续我们将54作为切分点,把前面和后面分成两个子列表并递归的执行上诉同样思想的操作就可以了。
快速排序的性质
最优时间复杂度:$O(nlog_2n)$
最坏时间复杂度:$O(n^2)$
稳定性:不稳定
快速排序代码实现
# start/end表示起始指针的位置(不是具体的值)
lst = list(map(int, input().split(',')))
def quick_sort(alist, start, end):
# 如果前指针的位置大于等于后指针的位置
if start >= end:
return
low = start
high = end
middle = alist[low]
while low < high:
while low < high and alist[high] >= middle:
high -= 1
alist[low] = alist[high]
while low < high and alist[low] <= middle:
low += 1
alist[high] = alist[low]
alist[low] = middle
quick_sort(alist, start, low - 1)
quick_sort(alist, low + 1, end)
quick_sort(lst, 0, len(lst) - 1)
print(lst)