一、前言
本博客将会通过快速排序的思想,用C语言行代码实现(递归,非递归,挖坑法,前后指针法,以及快慢指针都是需要掌握的重点)。最后在推算出时间复杂度,分析快排的优缺点,以及说明其稳定性。
看吧,此文的知识归纳量,还是挺全的,若觉得这篇博客,对你学习或工作方面有帮助,感谢一键三连+转发。废话不多说,正文开始。
二、快排的思想
随机选取一位数(常见的是起始,末尾,中间位置,选取起始位置的最常见)作为key,找到key的正确位置(key的正确位置用pivot表示)。 若是想要升序列,则保证该数右边比它大,该数左边比它小。若key左边,右边的都有序,我们就可以判定该组数据有序。
于是我们很容易就想到了分治(若左边无序,则对左边的数据,进行找key2所在的位置,再分一次区间。若key2左右区间仍无序,进行分区间,再次进行找key3.....,直到左右只剩一个元素,则判定有序。之后进行回归)
三、快排的代码实现
1.前言
经过对快排思想的深刻理解,我们就知道找key的正确位置pivot,则成为快排是否能实现的关键,而找pivot,则有三种方法(挖坑法,前后指针法,以及快慢指针)
而分治思想的的实践,有两种方法(递归,非递归)
下面所有代码的实现,都是以升序为目的
2.找到key的pivot
3. 分治算法的实现
四、快排的时间复杂度推导
五、快排的优缺点
1.假设一组数据,若每一次找key的pivot后,左区间接近为N,右区间接近为N-1,则消耗较大,最好理解的极端例子是,将一组数据逆序。这种情况有解决办法没有?当然有,那就是三数取中。
2.函数栈帧的创建有消耗,这种情况,在当前的CPU是完全可以忽略不计的,现在的CPU性能很强大,每秒能计算几亿次。函数栈帧创建最多的是最后几层,这种情况有解决办法没有?当然有,那就是子区间优化(因为快排对数据基础越大一组数列,更有优势,所以子区间优化,也能解决快排针对少数元素排序的性能浪费)。
3.递归深度过深会造成栈溢出,这种情况有解决办法没有?当然有,用数据结构中的栈模拟递归。
六、快排的优化
1.三数取中
2.子区间优化
七、快排的稳定性
1.何为稳定性?
稳定性指的是,相同的数据元素,再排序后,不改变他们的相对序列,即为稳定性。如这组数据{5A,5B,5C,9,3,2,5D},我将相同的5进行表记,若排序后为{2,3,5A,5B,5C,5D,9}。则代表快速排序稳定。
2.快排的稳定性?
可事实是,达不到上面要求的这个效果。所以不稳定。
八、快排的源代码
排序/排序 · 残风也想永存/C语言项目 - 码云 - 开源中国 (gitee.com)
里面包含了所有排序的源代码,若想要逐一验证,可点开此链接,跳转至我的码云。