• 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);
  • 相关阅读:
    我是菜鸟,开始学习计划
    我是菜鸟,学习计划4月19日笔录
    用HttpSessionListener与HttpSessionBindingListener实现在线人数统计
    mac系统InetAddress.getLocalHost().getHostAddress() 很慢
    获取n位数m进制的随机数 js
    cordova开发环境搭建
    遇到网页中无法选择的文本时或需要登录才可复制时可用
    今天摸的鱼就是以后加的班
    国际化vuei18n 向语言包中传入参数
    vue3 技术浏览 收藏
  • 原文地址:https://www.cnblogs.com/haoqiyouyu/p/14901891.html
Copyright © 2020-2023  润新知