快速排序
快排算是应用中广泛的排序算法了。由于实现简单,适用于不同的输入数据且在一般应用中比其他排序算法要快。快排的一个特点是原地排序,内循环比大多数排序算法要短小。它的主要缺点是非常脆弱,在实现中要非常小心才能避免低劣的性能。
快排是一种分治的排序算法。它将一个数组分成两个子数组,将两部分独立地排序。快排和归并排序是互补的:归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以将整个数组排序,递归调用发生在处理整个数组之前;而快排将数组排序的方式则是当两个子数组都有序时整个数组自然也就有序了,递归调用发生在处理整个数组之后。
按照《算法第4版》中的例子,实现一个标准的python解法。
1 | import random |
写法二:
1 | def sortArray(self, nums: List[int]) -> List[int]: |
性能分析:
- 内循环使用一个递增的索引将数组元素和一个定值比较,相对于归并和希尔的在内循环中移动数据的方法更快,更简洁。
- 比较的次数很少。排序效率依赖切分数组的效果。
基于Dijkstra-三路快排实现:当数组中包含大量重复的元素时,上述快排做出了一些无意义的切分。从左到右遍历数组,维护一个指针lt
使a[lo..lt-1]
中的元素都小于p,一个指针gt
使得a[gt+1..hi]
中的元素都大于p,一个指针i
使得a[lt..i-1]
中的元素都等于p,由于Python可以返回元组,所以改写成三路非常简单。
1 | import random |
冒泡排序
1 | def sortArray(self, nums: List[int]) -> List[int]: |
选择排序
1 | def select_sort(nums: list) -> list: |
插入排序
1 | def insertion(ary: list) -> list: |
希尔排序
使用切片的方式实现了一个简单的希尔排序,但是希尔排序应该是不产生空间的。
1 | def shell_sorted(nums): |
归并排序
原地归并
1 | def merge_sort(nums: list): |
自底向上的归并排序。_merge
方法都是一样的。
1 | def merge_sort_bu(nums: list): |
堆排序
将数组构建成堆,从最后一个非叶子节点n//2-1
对每个节点进行sink操作,完成heapify。
从堆顶最大的元素,和末尾互换,然后将堆顶元素下沉。
1 | def heap_sort(ary): |