一.快速排序的思想
快速排序可以认为是冒泡排序的升级版,它最重要的思想是分而治之。
比如我们有如上这样一段数字需要排序:
第一步:随机选择一个数字,假设选择65
第二步:通过算法,将所有小于65的数字放在65的左侧,将大于65的数字放在65的右侧
第三步:递归的处理左边的数字(比如选择31来处理左侧),递归的处理右侧的数字(比如选择81来处理右侧的数字)
最终:排序完成
那么快速排序和冒泡排序的区别在哪里呢?
在快速排序中,选择的65可以一次性的放在最正确的位置,之后不需要任何移动,即快速排序对数字的定位是一次性的
而冒泡排序需要将数字两两比较,找到最大值,并不断向后移
二.快速排序的枢纽
比较优秀的解决方案就是:取头、中、尾的中位数,比如8,12,3的中位数就是8
快速排序的选择枢纽代码如下:
//选择枢纽
ArrayList.prototype.median = function(left,right){
// 1.取出中间的位置
var center = Math.floor((left + right) / 2)
// 2.判断大小,并且进行交换
if(this.array[left] > this.array[right]){
this.swap(left,right)
}
if(this.array[left] > this.array[center]){
this.swap(left,center)
}
if(this.array[center] > this.array[right]){
this.swap(center,right)
}
// 3.将center换到right-1的位置
this.swap(center,right - 1)
return this.array[right - 1]
}
三.快速排序的代码
ArrayList.prototype.quickSort = function(){
this.quick(0, this.array.length - 1)
}
ArrayList.prototype.quick = function(left, right){
// 1.结束条件
if(left >= right) return
// 2.获取枢纽
var pivot = this.median(left, right)
// 3.定义变量,用于记录当前找到的位置
var i = left
var j = right - 1
// 4.开始进行交换
while(true){
while(this.array[++i] < pivot){}
while(this.array[--j] > pivot){}
if(i < j){
this.swap(i, j)
}else{
break
}
}
// 6.将枢纽放在正确的位置,i位置
this.swap(i, right - 1)
// 7.分而治之
this.quick(left, i - 1)
this.quick(i + 1, right)
}
四.快速排序的效率
快速排序的平均效率:为O(N*logN),它是目前排序中最好的
刷题期间发现,有一些大厂会让默写快排,这种使用Math.random()会更方便一下,借鉴大佬的代码
let quickSort = (arr) => {
quick(arr, 0 , arr.length - 1)
}
let quick = (arr, left, right) => {
let index
if(left < right) {
// 划分数组
index = partition(arr, left, right)
if(left < index - 1) {
quick(arr, left, index - 1)
}
if(index < right) {
quick(arr, index, right)
}
}
}
// 一次***
let partition = (arr, left, right) => {
// 取中间项为基准
var datum = arr[Math.floor(Math.random() * (right - left + 1)) + left],
i = left,
j = right
// 开始调整
while(i <= j) {
// 左指针右移
while(arr[i] < datum) {
i++
}
// 右指针左移
while(arr[j] > datum) {
j--
}
// 交换
if(i <= j) {
// swap(arr, i, j)
[arr[i],arr[j]] = [arr[j],arr[i]];
i += 1
j -= 1
}
}
return i
}
// 测试
let arr = [1, 3, 2, 5, 4]
quickSort(arr)
console.log(arr) // [1, 2, 3, 4, 5]
// 第 2 个最大值
console.log(arr[arr.length - 2]) // 4