快速排序 | 青训营笔记

254 阅读2分钟

原理介绍

快速排序(Quick Sort)是一种基于分治思想的常用排序算法。它的基本思想是选择一个基准元素(pivot),将待排序序列分成两个子序列,比基准元素小的放在左边,比基准元素大的放在右边。然后对左右两个子序列分别递归地进行快速排序,直到子序列的长度为1或0,排序完成。

快速排序的优点是平均时间复杂度为O(nlogn),排序速度较快。但是它的最坏时间复杂度为O(n^2),当待排序序列为有序或近似有序时,效率可能会比较低。

快速排序是一种利用分治思想的排序方法,确定主轴及分区是快速排序的核心操作。首先在数组中确定一个主轴元素 (例如以第一个元素为主轴元素),然后遍历数组,将数组分为两部分, 小于 主轴的元素放在 (最终的) 主轴下标 p 的左侧, 大于等于主轴的放在右侧,这个过程由后文介绍的「分区方法 partition 」实现。当前主轴位置确定后,继续递归地对主轴左右两侧数组执行这个过程,每次递归都传入待排序数组 arr 和本次要处理的部分的左右界,只处理这个范围内的序列。当所有递归都到达基准情形时,排序完成。因为是原地交换,递归过程中 arr 总是在动态排序,递归过程无需返回,为尾递归形式。

代码实现

排序的特性和主轴的选取有一定关系,本文仅暂时仅采用主轴为起始元素的方法。每次选取当前数组第一个元素作为主轴。

 func quickSortSimple(arr []int) []int {
     if len(arr) < 2 {
         return arr
     }
     quickSortSimpleRec(arr, 0, len(arr)-1)
     return arr
 }
 ​
 func quickSortSimpleRec(arr []int, l, r int) {
     if l < r {
         p := partition(arr, l, r)
         quickSortSimpleRec(arr, l, p-1)
         quickSortSimpleRec(arr, p+1, r)
     }
 }
 ​
 func partition(arr []int, l, r int) int {
     pivot := arr[l]
     for l < r {
         for l < r && arr[r] >= pivot {
             r--
         }
         arr[l] = arr[r]
         for l < r && arr[l] <= pivot {
             l++
         }
         arr[r] = arr[l]
     }
     arr[l] = pivot
     return l
 }