【算法】快速排序原理解析(原地快排)

444 阅读2分钟

1. 代码

function quickSort(arr, left, right) {
    var len = arr.length,
        partitionIndex,
        left = typeof left != 'number'? 0 : left,
        right = typeof right != 'number'? len - 1 : right;
 
    if(left < right) {
        partitionIndex = partition(arr, left, right);
        quickSort(arr, left, partitionIndex-1);
        quickSort(arr, partitionIndex+1, right);
    }
    return arr;
}
 
function partition(arr, left ,right) {
    var pivot = left,
        index = pivot + 1;
    for(var i = index; i <= right; i++) {
        if(arr[i] < arr[pivot]) {
            swap(arr, i, index);
            index++;
        }
    }
    swap(arr, pivot, index - 1);
    return index-1;
}

function swap(arr, i, j) {
    var temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

2. 思路

这种是原地快速排序的一种写法,主要是利用了递归分治的思路。 快速排序的思路是很简单的,就是选择一个基准点(pivot),然后遍历数组,把小于这个基准点的数值放到基准点的左边,大于基准点的数值放到右边。
但是本题的代码还是稍微有点复杂(对于我这种算法菜鸡来说),主要是理解这个partition方法,如果凭空想,还是有点费劲,需要在纸上或者打印日志看一下才能理解。

3. partition解释

这里主要解释一下partition这个方法,需要注意的是
这里选取的pivot是数组的左边界,这点有点奇怪的,我半天没反应过来,但是也不妨碍代码实现功能。
这里一共有三个变量(1)index (2)i (3)pivot
i就是用来遍历数组的,这个不用多说
index: 只有在发现arr[i]的值小于选定的中间值,才会交换arr[i]和arr[index],并且才index++。
关键在这里,理解一下,也就是说,比pivot小的数,到最后都会换到index的左边,那么一遍遍历完成之后,index就变成了小大数组的分界线,然后我们把pivot和index-1交换一下位置,是不是就完成了左小右大了。

4. patition流程图

image.png