文章目录
基本概念
1. 时间复杂度(Time Complexity)
- 释义:描述算法执行时间随输入规模增长而变化的趋势。通常用大O符号表示,如O(n)、O(n log n)等。
- 示例:快速排序的平均时间复杂度为O(n log n)。
2. 空间复杂度(Space Complexity)
- 释义:描述算法运行过程中所需额外存储空间随输入规模增长而变化的趋势。同样用大O符号表示。
- 示例:归并排序的空间复杂度为O(n),因为需要额外的数组来存储中间结果。
3. 稳定性(Stability)
- 释义:如果一个排序算法能够保证相等元素的相对顺序在排序后不改变,则称该算法是稳定的。
- 示义:插入排序是稳定的,因为它在插入新元素时不会改变已排序部分中相同元素的相对顺序。
4. 原地排序(In-place Sorting)
- 释义:如果一个排序算法只需要常数级别的额外空间来进行排序操作,则称该算法为原地排序算法。
- 示例:堆排序和快速排序都是原地排序算法,因为它们只需要O(1)的额外空间。
5. 比较排序(Comparison Sort)
- 释义:通过比较元素之间的大小关系来进行排序的算法。所有基于比较的排序算法的时间复杂度下界为O(n log n)。
- 示例:冒泡排序、选择排序、快速排序等都是比较排序。
6. 非比较排序(Non-comparison Sort)
- 释义:不依赖于元素之间的直接比较来进行排序的算法。这类算法通常利用数据的特殊性质(如数字范围)来实现更高效的排序。
- 示例:计数排序、基数排序和桶排序都属于非比较排序。
7. 最坏情况(Worst Case)
- 释义:指输入数据使得算法执行时间最长的情况。通常用于评估算法在极端条件下的性能。
- 示例:快速排序的最坏情况时间复杂度为O(n²),即当每次划分都极不平衡时。
8. 最好情况(Best Case)
- 释义:指输入数据使得算法执行时间最短的情况。用于评估算法在理想条件下的性能。
- 示例:快速排序的最好情况时间复杂度为O(n log n),即当每次划分都非常平衡时。
9. 分治法(Divide and Conquer)
- 释义:一种算法设计思想,将一个问题分解成若干个较小的子问题,分别解决这些子问题,然后合并它们的结果以得到最终解。
- 示例:归并排序和快速排序都是典型的分治法应用。
10. 基准(Pivot)
- 释义:在快速排序中,选择的一个元素作为基准,用于将数组划分为小于基准和大于基准的两部分。
- 示例:在快速排序中,可以选择数组的第一个元素作为基准。
11. 堆(Heap)
- 释义:一种特殊的完全二叉树结构,分为最大堆和最小堆。最大堆中每个节点的值大于或等于其子节点的值,最小堆则相反。
- 示例:堆排序利用最大堆来实现排序,首先构建最大堆,然后依次取出堆顶元素并重新调整堆。
12. 增量序列(Increment Sequence)
- 释义:希尔排序中使用的间隔序列,决定了每次分组时的步长。
- 示例:常用的增量序列有Shell增量序列和Hibbard增量序列。
13. 桶(Bucket)
- 释义:桶排序中用于存放特定范围内元素的容器。每个桶独立排序后再合并。
- 示例:假设待排序的数据范围为[0, 100],可以将其分为10个桶,每个桶存放10个数值范围内的元素。
14. 基数(Radix)
- 释义:基数排序中,基数指的是每个数位上的可能取值范围。例如,十进制数的基数为10,二进制数的基数为2。
- 示例:对于十进制整数,基数为10,表示每一位上有0到9这10个可能的值。
排序算法
排序算法是计算机科学中的基础算法之一,广泛应用于各种场景。以下是十种经典的排序算法及其特点、时间复杂度的总结。
1. 冒泡排序(Bubble Sort)
原理
重复地遍历要排序的数组,一次比较两个相邻元素,如果它们的顺序错误就把它们交换过来。
时间复杂度
- 最好情况:O(n)
- 平均情况:O(n²)
- 最坏情况:O(n²)
空间复杂度
- O(1)
稳定性
- 稳定
2. 选择排序(Selection Sort)
原理
每次从未排序的部分中选出最小(或最大)的元素,将其放到已排序部分的末尾。
时间复杂度
- 最好情况:O(n²)
- 平均情况:O(n²)
- 最坏情况:O(n²)
空间复杂度
- O(1)
稳定性
- 不稳定
3. 插入排序(Insertion Sort)
原理
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
时间复杂度
- 最好情况:O(n)
- 平均情况:O(n²)
- 最坏情况:O(n²)
空间复杂度
- O(1)
稳定性
- 稳定
4. 希尔排序(Shell Sort)
原理
对插入排序的一种改进,通过逐步缩小间隔来减少移动次数。
时间复杂度
- 最好情况:O(n log n)
- 平均情况:取决于增量序列的选择
- 最坏情况:O(n (log n)²)
空间复杂度
- O(1)
稳定性
- 不稳定
5. 归并排序(Merge Sort)
原理
将数组分成两半,分别对每一半进行排序,然后将两个有序的部分合并成一个有序的整体。
时间复杂度
- 最好情况:O(n log n)
- 平均情况:O(n log n)
- 最坏情况:O(n log n)
空间复杂度
- O(n)
稳定性
- 稳定
6. 快速排序(Quick Sort)
原理
通过选择一个“基准”元素,将数组分成小于基准和大于基准的两部分,递归地对这两部分进行排序。
时间复杂度
- 最好情况:O(n log n)
- 平均情况:O(n log n)
- 最坏情况:O(n²)
空间复杂度
- O(log n)
稳定性
- 不稳定
7. 堆排序(Heap Sort)
原理
利用堆这种数据结构来实现排序。首先构建最大堆,然后依次取出堆顶元素并重新调整堆。
时间复杂度
- 最好情况:O(n log n)
- 平均情况:O(n log n)
- 最坏情况:O(n log n)
空间复杂度
- O(1)
稳定性
- 不稳定
8. 计数排序(Counting Sort)
原理
适用于范围有限的整数排序。通过计数每个值出现的次数来确定排序后的顺序。
时间复杂度
- 最好情况:O(n + k)
- 平均情况:O(n + k)
- 最坏情况:O(n + k)
空间复杂度
- O(k)
稳定性
- 稳定
9. 桶排序(Bucket Sort)
原理
将待排序的数据分到若干个桶中,每个桶单独排序后再合并。
时间复杂度
- 最好情况:O(n + k)
- 平均情况:O(n + k)
- 最坏情况:O(n²)
空间复杂度
- O(n + k)
稳定性
- 稳定
10. 基数排序(Radix Sort)
原理
通过逐位处理数字来实现排序。每次处理一位时,使用计数排序或其他线性时间排序算法对当前位上的所有数字进行排序。
时间复杂度
- 最好情况:O(d * (n + k))
- 平均情况:O(d * (n + k))
- 最坏情况:O(d * (n + k))
空间复杂度
- O(n + k)
稳定性
- 稳定
总结
排序算法 | 时间复杂度 (最好) | 时间复杂度 (平均) | 时间复杂度 (最坏) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(n) | O(n²) | O(n²) | O(1) | 稳定 |
选择排序 | O(n²) | O(n²) | O(n²) | O(1) | 不稳定 |
插入排序 | O(n) | O(n²) | O(n²) | O(1) | 稳定 |
希尔排序 | O(n log n) | 取决于增量序列 | O(n (log n)²) | O(1) | 不稳定 |
归并排序 | O(n log n) | O(n log n) | O(n log n) | O(n) | 稳定 |
快速排序 | O(n log n) | O(n log n) | O(n²) | O(log n) | 不稳定 |
堆排序 | O(n log n) | O(n log n) | O(n log n) | O(1) | 不稳定 |
计数排序 | O(n + k) | O(n + k) | O(n + k) | O(k) | 稳定 |
桶排序 | O(n + k) | O(n + k) | O(n²) | O(n + k) | 稳定 |
基数排序 | O(d * (n + k)) | O(d * (n + k)) | O(d * (n + k)) | O(n + k) | 稳定 |
计数排序、桶排序、基数排序属于非比较类排序,其他七种是比较类排序。
每种排序算法都有其优缺点和适用场景,选择合适的排序算法可以大大提高程序的性能和效率。