「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」
介绍
快速排序是一个经典的排序算法,在待排序的记录中任取一个记录(通常取第一个)作为枢纽,设其关键字为pivotkey,经过一趟排序后,把记录值小于pivotkey的交换到前面,大的交换到后面,将待排序记录分成两个表,分别对两个表重复上述过程,直到每一子表只有一个记录。
特点
快速排序是对冒泡排序的一种改进,时间复杂度为,平均情况是O(nlogn),最坏情况是O(n^2)。最坏情况也就是当排序已经成为基本有序状态时。他的特点如下:
- 不稳定的排序,也就是如果相同的两个数字,无法保证其相对位置不发生变化。
- 排序过程需要定位表的下界和上界,所以适用于顺序结构,很难用于链式结构
- 当n较大时,在平均情况下快速排序是所有内部排序方法中速度最快的一种,所以其适合初始记录无序,n较大情况
步骤
现在有一个数组[49,38,65,97,76,13,27,49],我们需要通过快速排序算法对其进行排序。下面我们就来解析第一趟的运行逻辑。
第一步:设置第一个数 49 位枢纽,令 i = 0, j= n-1,从数组末尾开始遍历令j=j-1,直到找出比枢纽值小的数,找到27,因为是右往左第一个比枢纽值小的数,然后把它赋值给 i的位置。这时候的数组
/*
枢纽值:49
(27), 38, 65, 97, 76, 13, 27, 49
位置 i j
*/
第二步:然后再从左边i的位置开始遍历令i=i+1,直到找出比枢纽值第一个大的数,为 65,然后把它赋值到 j的位置。这时候的数组
/*
枢纽值:49
27, 38, 65, 97, 76, 13, (65), 49
位置 i j
*/
第三步:重复上述两步骤,直到 i === j 为止,这时候再把枢纽值赋值给 j,到此,就完成了第一趟排序,这个位置的左边都小于枢纽值,右边都大于枢纽值。这时候的数组就完成了第一趟排序,
/*
枢纽值:49
27 38 13 (49) 76 97 65 49
位置 i==j
*/
这时候数组被分成了两部分,在分别对这两部分重复上面三个步骤,直到排序完成。
这个就是快速排序的详细步骤。
代码
JavaScript版
const quickSort = (array) => {
const sort = (arr, left = 0, right = arr.length - 1) => {
if (left >= right) {//如果左边的索引大于等于右边的索引说明整理完毕
return
}
let i = left
let j = right
const pivotkey = arr[i] // 取无序数组最后一个数为基准值
while (i < j) { //把所有比基准值小的数放在左边大的数放在右边
while (i < j && arr[j] >= pivotkey) { //找到一个比基准值小的数交换
j--
}
arr[i] = arr[j] // 将较小的值放在左边
while (j > i && arr[i] <= pivotkey) { //找到一个比基准值大的数交换
i++
}
arr[j] = arr[i] // 将较大的值放在右边
}
arr[i] = pivotkey // 将基准值放至中央位置完成一次循环(这时候 j 等于 i )
sort(arr, left, j-1) // 将左边的无序数组重复上面的操作
sort(arr, j+1, right) // 将右边的无序数组重复上面的操作
}
sort(array)
return array
}
总结
与直接插入算法比,一开始还是不太容易的,主要要搞清 i 和 j 的位置关系。