排序算法之——快速排序
1、序
作为一名前端开发工程师,算法也是不可以不略的一part,特别是排序,在项目实际开发中,也会经常用到。今天我们就一起重温一下,什么是快速排序,它是如何进行排序的,最后我们再手写一个快速排序。
2、什么是快速排序,如何进行排序呢?
快速排序( Quicksort )是对冒泡排序算法的一种改进,排序规则如下:
- 选择一个中心点Pivot(在这里我选择的是最左边的第一个值为中心点);
- 选定两个指针,分别是
L和R分别指向数组最左边和最右边的位置; - 将R指向的数据和Pivot作比较,大于则指针移动,继续比较,小于则将和
L指针指向的值进行替换;(原则就是右边的必须比Pivot大); - 将L指向的数据和Pivot作比较,小于则指针移动,继续比较,大于于则将和
R指针指向的值进行替换;(原则就是左边的必须比Pivot小); - 当
L和R指向重合时,则将Pivot的值放在指针所指的位置; - 此时数组可以以Pivot为中心点,分为左、右子序列,对左、右子序列进行上述步骤,指导左右子序列仅为一个值时,即完成排序;
3、举个例子
我么以数组 arr = [19, 97, 9, 17, 1, 8] 为例子。
- 首选,以左一为Pivot值,即Pivot=19,指针
L和R分别指向序列左边和右边

- 将
Pivot和arr[R]进行对比,19 > 8,Pivot大于arr[R],则将arr[R]赋值给arr[L](R指针在Pivot的右边,则当arr[R]小时,将arr[R]放在左边)

-
L指针向右移动,到L=1,Pivot和arr[L]进行对比,19 < 97 ,Pivot小于arr[L],则将arr[L]赋值给arr[R](L指针在Pivot的左边,则当arr[L]大时,将arr[L]放在右边)

-
R指针向右移动,到R=4,Pivot和arr[R]进行对比,19 > 1 ,Pivot大于arr[R],则将arr[R]赋值给arr[L]

L指针向右移动,到L=2,Pivot和arr[L]进行对比,19 > 9,Pivot大于arr[L],则L指针继续移动。(当Pivot大于arr[L]时,L指针继续移动,直到Pivot小于arr[L],或L、R指针重合为止 )

L指针向右移动,到L=3,Pivot和arr[L]进行对比,19 > 17,Pivot大于arr[L],则L指针继续移动。

L指针向右移动,到L=4, 此时L和R指针重合,则将Pivot赋值到arr[L]( 或者arr[R])上 。

- 以
Pivot为中心点,Pivot左边的为左子序列,Pivot右边的为右子序列,由于右子序列仅剩一个值,则不做操作,将左子序列再进行以上操作。

- 以左一为Pivot值,即Pivot=8,指针
L和R分别指向子序列左边和右边。

- R=3,将
Pivot和arr[R]进行对比,8 < 17,Pivot小于arr[R],则R指针继续向左移动。

R指向向左移动R=2,将Pivot和arr[R]进行对比,8 < 9,Pivot小于arr[R],则R指针继续向左移动。

R指向向左移动R=1,将Pivot和arr[R]进行对比,8 > 1,Pivot大于arr[R],则将arr[R]赋值给arr[L]。

L指针向右移动,到L=1, 此时L和R指针重合,则将Pivot赋值到arr[L]( 或者arr[R])上 。

- 以
Pivot为中心点,Pivot左边的为左子序列,Pivot右边的为右子序列,由于左子序列仅剩一个值,则不做操作,将右子序列再进行以上操作。

- 以左一为Pivot值,即Pivot=8,指针
L和R分别指向子序列左边和右边。

-
R=3,将
Pivot和arr[R]进行对比,9 < 17,Pivot小于arr[R],则R指针继续向左移动。 -
R指针向右移动,到R=2, 此时L和R指针重合,则将Pivot赋值到arr[L]( 或者arr[R])上 。
-
此时左右子序列均不可继续操作,则排序完成。

4、排序算法
这个排序算法最核心的地方就是要搞清楚循环点,以下是 JavaScript 代码
let arr = [19, 97, 9, 17, 1, 8];
console.log('原始值:', arr)
let sortArr = []
sortArr = quickSort(arr, 0, arr.length - 1)
console.log('排序结果:', sortArr)
function quickSort(arr, left, right) {
if(left >= right) return arr; // 当左指针下标大于右指针下标时,退出函数
let L = left
let R = right
let Pivot = arr[L] // 以最左指针指向的值为中心点
while(R > L) { // 右下标 大于 左下标时,退出循环(即左右相等时退出循环)
while ((R > L) && arr[R] >= Pivot ) { // 右指针指向的值 大于 中心点值,右指针向左移动,直到小于或R=L时退出循环
R--
}
if(L < R) { arr[L] = arr[R] } // 小于时,且L和R不相等时,将R指向的值赋予L指针指向的值
while ((R > L) && arr[L] <= Pivot) { // 左指针指向的值 大于 中心点值,左指针向左移动,直到大于或R=L时退出循环
L++
}
if(L < R) { arr[R] = arr[L] } // 大于时,且L和R不相等时,将R指向的值赋予L指针指向的值
if(L >= R) { arr[L] = Pivot } // 中心点赋值
}
quickSort(arr, left, R-1) // 将左子序列继续递归调用
quickSort(arr, R+1, right) // 将右子序列继续递归调用
return arr
}
5、小结
快速排序算法,理解起来其实不难,只要理解了原理,就好办了。但在编程的时候,我还是会遇到一些问题,特别是代码中的两重while循环,退出条件的编写十分重要,在编码的时候经常编到死循环,必须要一步一步慢慢的调试,才能真正的提高算法和编程水平。文章如有有写得不好的地方,欢迎指出。
本文介绍了快速排序算法,详细讲解了其排序规则,并通过举例说明了排序过程。文章还包含了快速排序的代码实现,强调了理解算法原理和正确设置循环退出条件的重要性。

4万+

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



