文章目录
快速排序 Quick Sort
1. Definition
对冒泡排序进行的改进,贯彻的是一种分治的思想:随机设定输入序列中的一个元素为基准元素(pivot),通过一趟复杂度为
O
(
n
)
O(n)
O(n) 的排序操作,将序列分为以基准元素为分界的两部分,使得左边的所有元素的值都小于基准元素,右边所有的值都大于基准元素,这个过程就是一趟快速排序。不断重复这样的操作,直到当前部分为空或者只剩下一个元素,结束。
我们可以用一个递推表达式来表示这样的一个过程的复杂度:
T
(
n
)
=
T
(
n
/
2
)
+
n
(0)
T(n)=T(n/2)+n\tag{0}
T(n)=T(n/2)+n(0)
通过这个表达式,我们也可以推出,快速排序的时间复杂度是
n
log
n
\bold{n\log{n}}
nlogn (即平均情况每次都将序列对分,且每趟进行对分都需要平均复杂度为
O
(
n
)
O(n)
O(n) )
2. Implementation
这里我们简单让第一个元素作为每一趟的基准元素:
void quickSort(int L, int R, ElementType* elements){
if(L >= R){
return;
}
int pivot = L;
for(int i = L; i < R; i++){
if(elements[pivot] >= elements[i]){
swap(pivot, i, elements);
pivot++;
}
}
swap(0, pivot - 1, elements);
// left part
quickSort(L, pivot - 1, elements);
// right part
quickSort(pivot + 1, R, elements);
}
3. Performance
快速排序的性能:
- 时间复杂度:平均为 O ( n log n ) O(n\log n) O(nlogn),最坏情况为 O ( n 2 ) O(n^{2}) O(n2)
- 空间复杂度:递归栈需要占据空间,平均为 O ( log n ) O(\log n) O(logn),最坏情况为 O ( n ) O(n) O(n),即 n n n 此递归
4. 快速排序的缺点 Disadvantage
4.1 这是一个不稳定的排序算法
4.1.1 排序算法的稳定性
首先,一个稳定的排序算法应该保证:这个算法不会改变原来相同元素的相对次序。例如:一个序列 1 , 2 , 5 , 2 , 6 1,2,5,2,6 1,2,5,2,6,显然经过排序之后,序列肯定是 1 , 2 , 2 , 5 , 6 1,2,2,5,6 1,2,2,5,6。但是我们可以看到,这个序列中存在两个值为 2 2 2 的元素,我们记第一个为 2 1 2_{1} 21,第二个为 2 2 2_{2} 22,那么,如果是一个稳定的算法,那这个算法肯定可以保证在排序之后的序列中, 2 1 2_{1} 21 始终在 2 2 2_{2} 22 前面。这就是排序算法的稳定性。
4.1.2 快排的稳定性
现在我们再来看看快速排序的稳定性。很简单,还是上面的例子,假如我们选取这两个元素中的一个作为基准元素的时候,得到的两个结果中的 2 2 2 的相对次序肯定是不同的,因为我们肯定会把另外一个元素划分到同一个部分中,而这样这两个过程得到的相对次序肯定是相反的,那么其中一个肯定与原来的相对次序不同,所以肯定是不稳定的。
4.2 算法难以保证平均复杂度
也就是:快速排序非常有可能退化成为一个冒泡排序,而显然这个时候的时间复杂度是
O
(
n
2
)
O(n^{2})
O(n2)。
例如:当我们每次找到的基准元素的位置都是最后一个位置,也就是说,我们这一趟快速排序操作实际上就是把基准元素放到了序列的最后(也就是基准元素是最大的元素),显然,事实上这就是一个冒泡排序了。
优化方法:
- 随机选取基准元素(但是事实上还是有很大概率发生退化)
- 三分快排(这可能是最好的方法,三分快排将序列分为三部分:小于基准值,基准值,大于基准值这三部分,也就是说,三分快排不对基准值相同的这部分元素进行划分,而是单独放在中间,不改变其相对次序,这样就保证了当序列中存在较多相同值的元素时算法的稳定性)
5. 使用类似快速排序的思想
5.1 查找第 k 个最小的元素
可以使用类似快速排序的思想:因为快速排序每次将确定 pivot的位置,其实就是确定了最小的第 pivot 个元素,我们可以在每次划分完比较这个 pivot 和 k 的值:
pivot == k,则这个划分标准值就是所求值pivot < k,则第k个元素在后面的子序列中,对子序列做相同的操作pivot > k,在前面的子序列中,对前面的子序列重复操作
最终,我们选取的这个标准值会收敛到 k,即找到我们所求的最小值
本文深入解析快速排序算法,探讨其定义、实现与性能表现,揭示快速排序的不稳定性和可能的复杂度退化问题,并提出优化策略。同时,文章还介绍了如何利用快速排序思想查找序列中的第k个最小元素。
219

被折叠的 条评论
为什么被折叠?



