本文详细解析JavaScript中的快速排序算法,阐述其通过基准值分割数据的核心思想。提供完整的partition分区函数与sort递归排序代码,并分析其最好、最坏及平均时间复杂度分别为O(nlog2n)、O(n^2)和O(nlog2n),同时指出该算法属于不稳定排序。
快速排序基本原理
快速排序是冒泡排序的改进版。它通过一趟排序将数据分割为独立的两部分,其中一部分的所有数据均小于另一部分的所有数据,随后对这两部分分别递归执行快速排序,直至整个数据序列有序。
一趟快速排序算法步骤
设待排序数组为A[0]……A[N-1],首先任意选取一个数据(通常选数组第一个数)作为基准数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。 一趟快速排序的算法是: 1)设置两个变量low、high,排序开始的时候:low=0,high=N-1; 2)以第一个数组元素作为基准数据,赋值给base,即base=A[0]; 3)从high开始向前搜索,即由后开始向前搜索(high--),找到第一个小于base的值A[high],将A[high]和A[low]互换; 4)从low开始向后搜索,即由前开始向后搜索(low++),找到第一个大于base的A[low],将A[low]和A[high]互换; 5)重复第3、4步,直到low=high;
JavaScript代码实现
代码如下:
function partition(elements, low, high){
//默认将左侧首元素作为基准元素
var base=elements[low];
while(low < high){
//从后往前搜索,直到找到比基准元素小的元素,并进行交换
while(low < high && elements[high] >= base) high--;
var swap1=elements[low];elements[low]=elements[high];elements[high]=swap1;
//从前往后搜索,直到找到比基准元素大的元素,并进行交换
while(low < high && elements[low] <= base) low++;
var swap2=elements[low];elements[low]=elements[high];elements[high]=swap2;
}
//返回基准元素的位置,作为序列的分割位置
return low;
}
function sort(elements, low, high){
if(low<high){
//将序列一分为二,分为分割位置的前后序列,前序列比分割位置的值小,后序列比分割位置的值大
var partitionPos=partition(elements, low, high);
//对前序列继续递归排序
sort(elements, 0, partitionPos-1);
//对后序列继续递归排序
sort(elements, partitionPos+1, high);
}
}
var elements = [3, 1, 5, 7, 2, 4, 9, 6, 10, 8];
console.log('before: ' + elements);
sort(elements, 0, elements.length-1);
console.log(' after: ' + elements);
算法性能分析
效率:
时间复杂度:最好:O(nlog2n),最坏:O(n^2),平均:O(nlog2n)。
空间复杂度:O(nlog2n)。
稳定性:不稳定。