快速排序

快速排序也是最常用的排序算法,和归并算法一样,快速排序也采用分治的方法,将原始数组分为较小的数组。(但是并没有像归并排序那样将它们分开)

思路:

1.从数组中选择中间一项作为主元;

2.创建两个指针,左边一个指向数组的第一项,右边指向数组最后一项。移动左指针直到我们找到一个比主元大的元素,接着,移动右指针直到找到一个比主元小的元素。然后交换它们,重复这个过程,直到左指针超过了右指针。这个过程是的比主元小的值都排在了主元之前,而比主元大的值都排在了主元之后,这一步叫划分操作。

3.接着,算法对划分的小数组(较主元小的值组成的子数组,以及较主元大的值组成的子数组)重复之前的两个步骤,直至数组以完全排序。

注意:划分的依据是根据指定的主元来进行的。选择主元有好几种方式,最简单的是选择第一项。然而研究表明对于几乎已排序的数组来说,这不是一个好的选择,它会导致该算法最差的表现,所以另一种方式是随机选择一个数组项或者是选择中间项。

function quickSort(array){
    quick(array, 0, array.length-1);
}
function quick(array, left, right){
    var index;
    if(array.length > 1){
        // 返回每次划分后的左指针的位置
        index = partition(array, left, right);
        if(left < index - 1){
            quick(array, left, index - 1)
        }
        if(index < right){
            quick(array, index, right)
        }
    }
}
// 划分过程
function partition(array, left, right){
    // 选择数组中间项作为主元
    // 定义左右两个指针
    var pivot = array[Math.floor(right + left) / 2],
        i = left,
        j = right;
    // 当左边指针超过右边指针时结束循环
    while(i <= j){
        // 移动左指针找到一个大于等于主元的项,然后停止移动左指针
        while(array[i] < pivot){
            // 若没有找到就移动左指针
            i++
        }
        // 移动右指针找到一个小于等于主元的项,然后停止移动右指针
        while(array[j] > pivot){
            // 若没有找到就移动右指针
            j--
        }
        // 左右指针停止后,判断两个指针的位置,
        if(i <= j){
            // 若左指针没有超过右指针,交换两项的值,并移动两个指针
            swap(array, i, j);
            i++;
            j--;
        }
    }
    // 返回左指针用来创建子数组
    // 当一次循环结束后,比主元小的项全部在主元的左侧
    return i
}