04 排序算法 | 青训营笔记

101 阅读4分钟

为什么要学习数据结构和算法

学习数据结构和算法是为了提高解决问题的效率和质量,它们是计算机科学和软件工程中的基础,能够帮助我们更好地组织和处理数据,并设计出高效的算法来解决各种计算问题。掌握数据结构和算法可以提升代码的性能、减少资源消耗,并且能够应对日益复杂的计算需求。无论是开发软件、设计算法还是进行系统优化,学习数据结构和算法都是必不可少的,它们是构建稳定、可扩展和可靠软件系统的基石。

部分语言使用的排序算法

Python:timesort

C++:introsort

Rust:pdqsort

Go(<=1.18): introsort

Go(1.19): pdqsort

经典排序算法

插入排序

将元素不断插入已经排好序的array中,插入排序是一种简单而有效的排序算法。它的基本思想是将待排序的序列分为已排序和未排序两部分,初始时已排序部分只有一个元素(即第一个元素),然后逐步将未排序部分的元素插入到已排序部分的合适位置,直到整个序列排序完成。具体实现时,通过不断比较当前元素与已排序部分的元素大小,找到合适的插入位置并将元素插入,然后将已排序部分的边界向右移动一个位置。插入排序的时间复杂度为O(n^2),适用于小规模数据或部分有序的情况,而且它是稳定的排序算法。尽管插入排序在大规模数据上效率较低,但由于其实现简单、易于理解和编写,也是学习排序算法的基础之一。

  • 最好时间复杂度:O(n)
  • 平均时间复杂度:O(n^2)
  • 最坏时间复杂度:O(n^2)

快速排序

快速排序是一种常用且高效的排序算法。它的基本思想是选择一个基准元素,将待排序的序列分为两部分,一部分是比基准元素小的元素,另一部分是比基准元素大的元素。然后递归地对这两部分进行快速排序,直到整个序列有序。具体实现时,通过选择合适的基准元素,可以使用分治法将序列不断划分为子序列,再对子序列进行排序。快速排序的时间复杂度平均情况下为O(nlogn),最坏情况下为O(n^2),但通常情况下它的性能非常好。快速排序是一种原地排序算法,不需要额外的存储空间,而且它是不稳定的排序算法。由于快速排序的高效性和普适性,它被广泛应用于各种排序场景,并且常常作为其他高级排序算法的基础。

  • 最好时间复杂度:O(n*log(n))
  • 平均时间复杂度:O(n*log(n))
  • 最坏时间复杂度:O(n^2)

堆排序

堆排序是一种高效的排序算法,它基于二叉堆的数据结构实现。堆是一种特殊的完全二叉树,具有一些特性,如父节点的值大于(或小于)其子节点的值。堆排序的基本思想是首先将待排序的序列构建成一个大顶堆(或小顶堆),然后反复将堆顶元素(最大值或最小值)与序列中的最后一个元素交换,并重新调整堆,使得剩余序列满足堆的特性。通过不断重复这个过程,最终可以得到一个有序的序列。堆排序的时间复杂度为O(nlogn),具有稳定的性能。堆排序适用于大规模数据和动态数据的排序,同时它也是不需要额外的存储空间的原地排序算法。由于其高效性和适应性,堆排序在实际应用中得到广泛应用,尤其在需要对大量数据进行排序或实时排序的场景中表现出色。

  • 最好时间复杂度:O(n*log(n))
  • 平均时间复杂度:O(n*log(n))
  • 最坏时间复杂度:O(n*log(n))

总结

  • 在所有短序列和元素有序情况下,插入排序性能最好
  • 在大部分的情况下,快速排序有较好的综合性能
  • 几乎在任何情况下,堆排序的表现都比较稳定