javascript 快速排序
Posted wayshon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript 快速排序相关的知识,希望对你有一定的参考价值。
概述
快排就是找一个基数用来比较
把比他大的放他前面,比他小的放他后面
然后把前后两部分重复此方法排序
通俗易懂版本
let list = [2, 3, 1, 9, 5, 6, 4, 7, 8];
let quick = function(arr) {
if (arr.length < 1) {
return arr;
}
let base = arr[0], left = [], right = [];
for (let i = 1; i < arr.length; i++) {
if (arr[i] < base) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
return arguments.callee(left).concat(base, quick(right))
}
let result = quick(list);
console.log(result)
这个方法比较简单,直接创建数组,把比基数小的放前面数组,大的放后面数组。然后利用数组合并就是排序后的数组。但是重复创建了很多数组对象,加上递归的原因,这里对性能是一种严重的浪费。
抽象版本
let quickSort = function(arr, startIndex, endIndex) {
if (startIndex > endIndex) {
return;
}
let left = startIndex, right = endIndex, base = list[startIndex];
while (left !== right) {
while (right > left && arr[right] >= base) {
right--;
}
while (left < right && arr[left] <= base) {
left++;
}
if (left < right) {
let temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
arr[startIndex] = arr[right];
arr[right] = base;
arguments.callee(arr, startIndex, left - 1);
arguments.callee(arr, left + 1, endIndex)
}
quickSort(list, 0, list.length - 1);
console.log(list)
- 这里就不是利用创建数组归类的方式了,而是直接修改原数组,避免了不必要的创建数组对象。缺点是看起来不是那么明朗。
- 首先缺点一个用来比较的基数(不一定是第一个数)
- 从数组最后向前找比基数小的数,找到一个就停下,此时
right
指向右边第一个比基数小的数。 - 从数组左边向后找比基数大的数,找到一个就停下,此时
left
指向左边第一个比基数大的数。 - 互换这两个数,这就保证了基数两边,左边是小的,右边是大的。
- 当
right
与left
碰头时,停止。因为此时left
遍历过的都是比基数小的,right
遍历过的都是比基数大的,没必要在找下去。 - 能让
right
指针停下来的数肯定是比基数小的数,因为这里基数是第一个,所以基数要与比它小的数换位置。 - 注:
left
停下的时候指向的是大于基数的数,要这个数没用,因为基数已经在第一个了,left
指向的数肯定在它后面,已经是正确的情况。如果我们取得基数是中间的某个值,这时候就得判断指针位置和数值大小再确定换不换位置。由于外层循环结束时right
位置使我们需要的位置,所以应该先从右往左开始找小的。如果先由左往右,left
指向一个比基数大的数停下了,这时候right
也与left
相遇了,但这时指向的数是比基数大的数,显然不是我们需要的。先从右开始就不一样了,right
锁定的是比基数小的,left
撞上right
时指向的数就是比基数小的数。 - 换一种说法:先从右找的原因是要找一个比基数小的跟基数换位,实现小的在基数前面。但是这样不能保证基数前面都比他小。所以还需要从前面找找比基数大的,找到了就和已经找到的小的数互换,找不到就是
right
与left
相遇,循环结束,将基数与right
指向的数换位。 - 最后把基数两边的数重复上面步骤。
以上是关于javascript 快速排序的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript 快速功能SublimeText 2片段