以前写过一篇快速排序,是参考阮一峰老师的文章。
最近买了一本叫《啊哈!算法》的书,内容易懂,适合我这种渣渣阅读。
书里的内容都是用C语言写的,但是算法的核心是不变的。
现在用javascript改写一下书中P12页快速排序的内容。
var quickSort=function(arr,left,right){
// 如果左边界比右边界大,返回结果,排序结束
if(left>right){
return;
}
// 默认值处理,如果有传入left和right参数,就赋值这个参数,否则就赋值后面的默认值
left=left||0;
right=right||arr.length-1;
// 定义移动的左游标和右游标
var leftPoint=left;
var rightPoint=right;
// 定义一个基准数
var temp=arr[left];
// 判断左右游标是否重合,如果重合,循环结束
while(leftPoint!=rightPoint){
// 基准数在左边,因此从右边开始一个个扫描
// 从右到左,寻找小于基准数的数,且左游标要小于右游标
// 如果数字大于基准数(证明不符合条件),寻找下一个
// 直到找到比基准数小的数,游标停止递减
while(arr[rightPoint]>=temp&&leftPoint<rightPoint){
rightPoint--;
}
// 从左到右,寻找大于基准数的数,且左游标要小于右游标
// 如果数字小于基准数(证明不符合条件),寻找下一个
// 直到找到比基准数小的数,游标停止递增
while(arr[leftPoint]<=temp&&leftPoint<rightPoint){
leftPoint++;
}
// 如果左游标小于右游标,则交换两个数字的位置
if(leftPoint<rightPoint){
var changeNumber=arr[leftPoint];
arr[leftPoint]=arr[rightPoint];
arr[rightPoint]=changeNumber;
}
// 进行下一次循环,直到两个游标重合位置
}
// 重合之后,交换基准数
arr[left]=arr[leftPoint];
arr[leftPoint]=temp;
// 递归操作左右两个数组
quickSort(arr,left,leftPoint-1);
quickSort(arr,leftPoint+1,right);
return arr;
};
var numArr=[6,1,2,7,9,4,5,10,8];
console.log(quickSort(numArr));
《啊哈!算法》中强调,如果基准数在左边的话,扫描一定要从右边开始。因为这是为了保证基准数调换位置之后左边的都比基准小,右边的都比基准大。
如果从左边开始,程序会在比基准大的一个数下停止,然后右边开始,右边极有可能会因为左右游标相遇而无法找到正确的,比基准小的数字而停住,这样就会导致左边出现比基准要大的数。
如果从左边开始,
请大家试着排序:
6 1 2 7 9 10 11
左游标找到一个7是比基准6大的,因此停住。
右游标要找一个数字是比基准6小的,但是走到7的时候因为两个游标相遇就无法继续往前走,这个时候,交换和基准的位置,就会变成:
7 1 2 6 9 10 11
这样就不符合我们的要求了。
网友评论