排序算法之快速排序

808 阅读2分钟

这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战

快速排序

  • 快速排序:使用分治的方法,将原始数组分为较小的数组。
  • 核心思想:
    • 首先,从数组中选择中间一项作为主元。
    • 接着,(进行划分操作):创建两个指针,左边一个指向数组的第一项,右边一个指向数组的最后一项。
    • 然后,移动左指针,直到找到一个比主元大的元素;接着移动右指针,找到一个比主元小的元素。然后交换它们,重复这个过程,直到左指针超过了右指针。
    • 在这个过程中会使得比主元小的元素,都排在主元之前,而比主元大的元素都排在主元之后。(划分操作结束)
    • 然后,算法对划分之后的小数组(较主元小的元素组成的子数组,以及较主元大的元素组成的子数组),重复之前的步骤,直到数组已完全排序。

实现

// 我们先声明一个主方法来调用递归函数,传递待排序数组,以及索引0及其最末的位置
function quickSort(array) {
    quick(array, 0, array.length -1)
}

// 实现quick递归函数
function quick(array, left, right) {
    // 定义index来标记 主元位置
    let index = null;
    // 数组大于1才进行排序
    if (array.length > 1) {
        // 由主元位置计算函数 得出主元位置index的值,初始时左指针为0,右指针为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) {
    // 首先。确定数组的中间下标的元素,作为主元
    let pivot = array[Math.floor((left + right) / 2)];
    // 初始化两个指针,分别是传进来的左指针0和右指针 length-1
    let i = left;
    let j = right;
    // 只要 两个指针之间没有相互交错,就开始循环,否则返回 i
    while(i <= j) {
        // 移动左指针,直到找到一个元素比 主元 大
        while(array[i] < pivot) {
            i++
        }
        // 接着移动右指针,直到找到一个元素比 主元 小
        while(array[j] > pivot) {
            j--
        }
        // 当左指针指向的元素比主元大 且 右指针指向的元素 比主元小,同时,此刻的左指针索引小于等于右指针。也就是说左项比右项大,的时候
        if(i <= j) {
            // 交换两项的位置
            let aux = array[i];
            array[i] = array[j]
            array[j] = aux;
            // 移动指针,以便下次操作,重复此过程
            i++
            j--
        }
    }
    // 整个划分结束之后,返回左指针的索引,用来创建子数组
    return i
}