08-快速排序/原地快排/二分排序

快速排序:

1.找一个基准值,比如把数组第一项作为基准值,作为数组内剩下的比较项;
拿基准值与数组内的每一项去比较,大于这个基准值的push进right数组内,小于的push到left数组内。
2.再用递归把left和right两个数组分别再按照这种逻辑拆分成左右数组,直到传入的数组length<1 length为0时,作为递归的终止条件。
3.终止条件return出去的要是一个arr 或者是一个空数组(因为没值符合了,已经拆分完了),为什么要返回空数组呢?而不是直接return掉呢?
因为最后是用拼接的方式把符合条件的放入到一个数组内了。并且是用...扩展运算符,所以只能是一个数组。
 
// 快速排序思想:
// 排队的时候,随便找一个人:小明 遍历一次,比小明矮的站在左边,反之站右边

var arr1 = [3, 44, 13, 8, 9, 7, 1, 2];

function quickSort1(arr) {
    if (arr.length < 1) return arr;
    let flag = arr[0];
    let left = [];
    let right = [];
    for (let i = 1; i < arr.length; i++) {
        if (flag > arr[i]) {
            left.push(arr[i])
        } else {
            right.push(arr[i])
        }
    }
    // 第一种写法
    let l = quickSort1(left);
    let r = quickSort1(right);
    return [...l, flag, ...r];
    // 第二种写法
    return quickSort1(left).concat([flag]).concat(quickSort1(right))
}

var res1 = quickSort1(arr1);
console.log(res1); // [1, 2,  3,  7, 8, 9, 13, 44]
// 复杂度:O(n * lgn)以2为底的x次方,一分为二
// 缺点:
// 有了left和right 两个变量,每次递归的时候都会声明这两个变量,占用空间太多

 原地快排:

由于快排每次递归会生成left和right两个数组(两个引用内存空间)浪费内存,我们用原地排序进行优化:

function qsort(arr, start, end) {
    if (start >= end) return
    let i = start,
        j = end
    let mid = arr[start]
    while (i < j) {
        // 当前后面的项>前面的,就让后面的j--,从后往前找
        while (i < j && arr[j] >= mid) {
            j--
        }
        // 直到打破了上面的while循环:后面的<前面的,拿到了打破条件的这个j的索引,
        // 那就把当前这一项赋值给前面的这一项(交换位置)
        if (i < j) {
            arr[i] = arr[j]
        }
        // 如果当前项<后面项,那就i++(前面的当然要排到前面了),从前往后查找
        while (i < j && arr[i] <= mid) {
            i++
        }
        // 直到当前项>后面项,那就交换位置(前面项大于后面项的话应该把前面项放在后面)
        if (i < j) {
            arr[j] = arr[i]
        }
    }
    // 继续
    qsort(arr, start, i - 1)
    qsort(arr, i + 1, end);
    // 当此轮循环i>=j的时候,打破了上面的循环,那么就让i对应的项变为mid(基准比较对象)
    arr[i] = mid
    return arr;
}
let array = [14, 8, 29, 7, 25, 13, 55, 14, 95, 8, 11, 6]
let resResult = qsort(array, 0, array.length - 1)
console.log(resResult);

 二分排序

var arr = [15, 2, 3, 6, 71, 28, 24, 25, 5, 1];

function fn(arr, start, end) {
    if (start > end) return [];
    if (start == end) return [arr[start]];
    let center = Math.floor((start + end) / 2);
    let left = fn(arr, start, center);
    let right = fn(arr, center + 1, end);
    let r = [];

    while (left.length > 0 || right.length > 0) {
        if (left[0] < right[0]) {
            r.push(left.shift())
        } else {
            r.push(right.shift())
        }
        if (left.length === 0) {
            r = r.concat(right)
            break;
        } else if (right.length === 0) {
            r = r.concat(left)
            break;
        }
    }
    return r;
}
var res = fn(arr, 0, arr.length - 1);
console.log(res);
原文地址:https://www.cnblogs.com/haoqiyouyu/p/14901891.html