• js 实现快速排序


    // 快速排序
    // 快速排序基本思路, 通过遍历,找到一个基准值,遍历一趟后,将所有比基准值小的放在基准值左边,比基准值大的放在基准值右边,这时候基准值就是一个排好序的数,再将基准值两边的数组分别调用此方法递归,最终生成有序数列
    //  1.左右指针交换法
    // 左右指针对向前进,当遇到左侧指针所指的数小于等于基准值,或右侧指针指向的数大于基准值,则循环会停止,交换左右指针对应的的数,否则指针继续向前,最后两个指针会指向同一个位置,将基准值与重合位置交换
    // 单趟排序的思路是:取区间中最左或最右边的元素为key,定义两个变量,这里假设是p和q,q从区间的最右边向左走,找到比key小的元素就停下。p从最左边向右走,找到比key大的元素就停下。然后交换p和q所指向的元素。
    function quickSort1(arr) {
        let tmpArr = [...arr]; //复制数组
        return quick1(tmpArr, 0, tmpArr.length - 1);
    }
    // 默认左指针从 0 开始,右指针从尾部开始
    function quick1(arr, i, j) {
        // 当左右指针索引值相减<=0,说明数组只有一个值了
        if (j - i <= 0) return;
        let left = i; // 定义左指针
        let right = j; // 定义右指针
        let base = left; // 以左边第一个为基准值的索引值
        let center = arr[base]; // 定义基准值
        // 循环条件,就是左指针小于右指针,当等于时,即停止
        while (left < right) {
            // 如果右侧指针指向的数小于基准值,则停止循环,否则继续向左移动一位
            while (left < right && center < arr[right]) {
                // 右侧指针继续向左移动一位
                right--;
            }
            // 如果左侧指针指向的数大于基准值,则停止循环,否则继续向右移动一位
            // 注意,左右指针遍历条件中至少有一个写=,否则会陷入死循环
            while (left < right && center >= arr[left]) {
                left++;
            }
            // 当上面两个循环停止,此时交换满足左指针指向的元素大于基准值,右指针指向的元素小于基准值,则将左右元素交换
            let temp = arr[right];
            arr[right] = arr[left];
            arr[left] = temp;
        }
        // 整体遍历结束后,说明 left=right,这时候左右指针相遇,则相遇的位置即为基准值应该被排好序的位置,这时候将基准值与相遇位置的元素进行交换
        let temp = arr[base];
        arr[base] = arr[left];
        arr[left] = temp;
        // 递归,这时候相遇位置的索引等于 left=right
        //分别递归左右两侧
        // left=right 位置已经是排好序的了
        quick1(arr, i, left - 1);
        quick1(arr, left + 1, j);
        return arr;
    }
    console.log("快速排序-左右指针交换法");
    console.log(quickSort1([6, 3, 7, 8, 2, 4, 0, 1, 6, 5]));
    
    // 2.挖坑法,每次把坑位与指针位置交换
    // 取最左或最右边的元素为key,假设把这个位置“挖空”,让最右边的q向左走,直到遇到比key小的数,将其放到key的位置,自己的位置变“空”。直到pq相遇,那么这个位置就是最终的坑位,再将key填入这个坑位,就完成了一趟排序。
    function quickSort2(arr) {
        let tmpArr = [...arr]; //复制数组
        return quick2(tmpArr, 0, tmpArr.length - 1);
    }
    function quick2(arr, i, j) {
        if (j - i <= 0) return; //说明数组只有一个值了
        let left = i;
        let right = j;
        let base = left; //以左边第一个为基准值
        let center = arr[base];
        while (left < right) {
            // 如果右侧指针指向的数小于基准值,则停止循环,否则继续向左移动一位
            while (left < right && center < arr[right]) {
                right--;
            }
            if (left < right) {
                // 右指针找到了比基准值小的值,与基准值交换位置
                arr[base] = arr[right];
                arr[right] = center;
                base = right;
                // 左指针继续向前
                left++;
            }
            // 如果左侧指针指向的数大于基准值,则停止循环,否则继续向右移动一位
            while (left < right && center > arr[left]) {
                left++;
            }
            if (left < right) {
                // 左指针找到了比基准值大的值,与基准值交换位置
                arr[base] = arr[left];
                arr[left] = center;
                base = left;
                // 右指针继续向左
                right--;
            }
        }
        quick2(arr, i, base - 1); //分别处理左右两侧
        quick2(arr, base + 1, j);
        return arr;
    }
    console.log("快速排序-挖坑法");
    console.log(quickSort2([6, 3, 7, 8, 2, 4, 0, 1, 6, 5]));
    
    // 3.额外定义两个数组实现,最简单,空间复杂度最高
    function quickSort3(arr) {
        if (arr.length <= 1) return arr;
        const num = arr[0];
        let left = [],
            right = [];
        for (let i = 1; i < arr.length; i++) {
            if (arr[i] <= num) {
                left.push(arr[i]);
            } else {
                right.push(arr[i]);
            }
        }
        return quickSort3(left).concat([num], quickSort3(right));
    }
    console.log("快速排序-创建数组法");
    console.log(quickSort3([6, 3, 7, 8, 2, 4, 0, 1, 6, 5]));
    console.log(quickSort3([1, 2, 3, 4, 5, 6, 7, 8, 9, 9]));
    
    // 4.快慢指针法
    // 取最左边的数为key,定义两个快慢指针,都从key的下一位往右走,fast每走一步判断一下它指向的元素是否小于key,若小于则交换fast和slow位置的元素,并且让slow向前走,直到fast走到底,结束循环。最后让slow和key位置的值交换。再返回key的位置。

    参考链接:

    https://www.imooc.com/article/73247

    https://blog.csdn.net/xinxxxxxxxxx/article/details/123032933

  • 相关阅读:
    request 请求 转 json
    图片缩略图 简单应用
    文件压缩下载 和 解压缩并解析
    简单 map 与 xml 互转
    SVN+vs2017
    cordova生成签名的APK
    海关 实时数据 企业联调接口 总结
    vs2017远程调试
    X509证书 指定了无效的提供程序类型 System.Security.Cryptography.CryptographicException 错误解决方法
    微信公众号开发 ,redirect_uri域名还是与后台配置不一致
  • 原文地址:https://www.cnblogs.com/beileixinqing/p/16652895.html
Copyright © 2020-2023  润新知