已发布·持续改进
Algorithm
排序算法把数据按顺序排列。本主题涵盖归并排序、快速排序、堆排序、稳定性、n log n 下界、计数排序与各语言的内置排序。
排序是把元素按数值、字母或时间等既定顺序重新排列的算法。它大致分为两类:比较排序(冒泡排序、插入排序、选择排序、归并排序、快速排序、堆排序)只通过比较两个元素来决定先后;非比较排序(如计数排序和基数排序)则直接利用整数的值或各位数字。
排序是二分查找、去重、区间合并、排名等大量任务的前置步骤,因此是最先学习的基础算法之一。了解比较排序在最坏情况下至少需要 Ω(n log n) 次比较这一下界、稳定排序与原地排序的区别,以及 Python 的 Timsort、多数 C++ std::sort 实现所采用的内省排序等内置排序的行为,能帮助你在工程实践和技术面试中做出正确选择。
学习时,建议先在小数组上手动追踪插入排序、归并排序和快速排序的过程,再亲自实现归并排序和快速排序,并比较它们的最好、平均和最坏复杂度。之后练习用 key 函数和比较器调用内置排序,并解决区间合并、逆序对计数等基于排序的问题。
归并排序把输入一分为二再合并,快速排序围绕基准值进行划分。两者的平均时间复杂度都是 O(n log n)。
稳定排序保持相等键元素的原始顺序,原地排序几乎不占用额外内存。哪一点更重要取决于具体任务。
决策树论证表明,任何比较排序在最坏情况下都需要 n log n 数量级的比较次数。归并排序和堆排序达到了这个下界。
计数排序和基数排序不比较元素,能在接近线性的时间内对取值范围或位数有限的整数排序。
merge_sort 把列表一分为二,分别递归排序,然后每次取两个有序列表开头较小的元素,把它们合并成一个列表。相等时先取左边的元素(<=),因此是稳定排序,并且对任何输入都是 O(n log n)。最后一行检查结果是否与内置的 sorted() 一致。
merge_sort.py
def merge_sort(items):
"""Return a new sorted list (stable, O(n log n))."""
if len(items) <= 1:
return list(items)
mid = len(items) // 2
left, right = merge_sort(items[:mid]), merge_sort(items[mid:])
merged, i, j = [], 0, 0
while i < len(left) and j < len(right):
if left[i] <= right[j]: # take the left one on ties: stable
merged.append(left[i])
i += 1
else:
merged.append(right[j])
j += 1
return merged + left[i:] + right[j:]
if __name__ == "__main__":
data = [38, 27, 43, 3, 9, 82, 10]
print(merge_sort(data)) # [3, 9, 10, 27, 38, 43, 82]
print(merge_sort(data) == sorted(data)) # True
python merge_sort.py共六章,带你从安装一步步了解 排序 的核心概念。
在这里提问、分享经验,交流关于 排序 的看法。
还没有讨论。来发起第一个吧。
0 条评论
登录 · 登录后即可发表评论。
来发表第一条评论吧。