经典排序

92 阅读2分钟

插入排序

image.png || 将元素不断插入已经排好序的array中

  • 起始只有一个元素5,本身就是一个有序序列
  • 后续元素插入有序序列(5所在的序列)中,不断交换,直到找到第一个比其小的元素
缺点

平均和最坏情况的时间复杂度为O(n^2)

优点

最好情况时间复杂度为O(n)

快速排序

image.gif || 分治思想,不断分割序列直到序列整体有序

  1. 选定一个pivot(轴点)
  2. 使用pivot分割序列,分成元素比pivot大和元素比pivot小两个序列
缺点

最坏情况的时间复杂度高达O(n^2)

优点

平均情况的时间复杂度为O(n^logn)

堆排

利用堆的性质形成的排序算法

  • 构造一个大顶堆
  • 将根节点(最大元素)交换到最后一个位置,调整整个堆,如此反复
缺点

最好情况的时间复杂度高达O(n^logn)

优点

最坏情况的时间复杂度为O(n^logn)

对比

  • 插入排序在短序列中速度最快
  • 快速排序在其他情况中速度最快
  • 堆排序速度于最快算法差距最大

结合三种方法的优点

  • 对于短序列(小于一定长度),我们使用插入排序
  • 其他情况,使用快速排序来保证整体性能
  • 当快速排序表现不佳时,使用堆排序来保证最坏情况下时间复杂度仍然为O(n*logn)

Q&A

1.短序列的具体长度是多少?

  • 12~32,在不同语言和场景中会有不同,在泛型版本根据测试选定24
  1. 如何得知快速排序表现不佳,以及何时切换到堆排序?
  • 最终pivot的位置序列两端距离很接近时(距离小于length/8)判定其表现不佳,当这种情况的次数达到limit(即bits.len(length))时,切换到堆排序。