• js 常用排序


     冒泡排序

    原理:从第一个元素开始,把当前元素和下一个索引元素进行比较。如果当前元素大,那么就交换位置,重复操作直到比较到最后一个元素
     function bubbleSort(arr) {
          if (Array.isArray(arr)) {
            for (var i = arr.length - 1; i > 0; i--) {
              for (var j = 0; j < i; j++) {
                if (arr[j] > arr[j + 1]) {
                  [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
                }
              }
            }
            return arr;
          }
        }

    插入排序

    原理:第一个元素默认是已排序元素,取出下一个元素和当前元素比较,如果当前元素大就交换位置。那么此时第一个元素就是当前的最小数,所以下次取出操作从第三个元素开始,向前对比,重复之前的操作。

    function insertSort(arr) {
          if (Array.isArray(arr)) {
            for (var i = 1; i < arr.length; i++) {
              var preIndex = i - 1;
              var current = arr[i]
              while (preIndex >= 0 && arr[preIndex] > c) {
                arr[preIndex + 1] = arr[preIndex];
                preIndex--;
              }
              arr[preIndex + 1] = current;
            }
            return arr;
          }
        }

    选择排序

    原理:遍历数组,设置最小值的索引为 0,如果取出的值比当前最小值小,就替换最小值索引,遍历完成后,将第一个元素和最小值索引上的值交换。如上操作后,第一个元素就是数组中的最小值,下次遍历就可以从索引 1 开始重复上述操作。

        function selectSort(arr) {
          if (Array.isArray(arr)) {
            for (var i = 0; i < arr.length - 1; i++) {
              var minIdex = i;
              for (var j = i + 1; j < arr.length; j++) {
                minIdex = arr[j] < arr[minIdex] ? j : minIdex;
              }
              [arr[i], arr[minIdex]] = [arr[minIdex], arr[i]];
            }
            return arr;
          }
        }

    快速排序

    原理:在数据集之中,找一个基准点,建立两个数组,分别存储左边和右边的数组,利用递归进行下次比较。

    function quickSort(arr) {
          if (!Array.isArray(arr)) return;
          if (arr.length <= 1) return arr;
          var left = [], right = [];
          var num = Math.floor(arr.length / 2);
          var numValue = arr.splice(num, 1)[0];
          for (var i = 0; i < arr.length; i++) {
            if (arr[i] > numValue) {
              right.push(arr[i]);
            } else {
              left.push(arr[i]);
            }
          }
          return [...quickSort(left), numValue, ...quickSort(right)]
        }

    希尔排序

    原理:

    选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
    按增量序列个数 k,对序列进行 k 趟排序;
    每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
     function shellSort(arr) {
          var len = arr.length,
            temp,
            gap = 1;
          // 动态定义间隔序列,也可以手动定义,如 gap = 5;
          while (gap < len / 5) {
            gap = gap * 5 + 1;
          }
          for (gap; gap > 0; gap = Math.floor(gap / 5)) {
            for (var i = gap; i < len; i++) {
              temp = arr[i];
              for (var j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
                arr[j + gap] = arr[j];
              }
              arr[j + gap] = temp;
            }
          }
          return arr;
        }

    归并排序

    原理:

    (1) 把长度为n的输入序列分成两个长度为n/2的子序列;
    (2)对这两个子序列分别采用归并排序;
    (3) 将两个排序好的子序列合并成一个最终的排序序列。
    let arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
    
    function mergeSort(arr) {  //采用自上而下的递归方法
          var len = arr.length;
          if (len < 2) {
            return arr;
          }
          var middle = Math.floor(len / 2),
            left = arr.slice(0, middle),
            right = arr.slice(middle);
          return merge(mergeSort(left), mergeSort(right));
        }
    
        function merge(left, right) {
          var result = [];
          while (left.length && right.length) {
            // 不断比较left和right数组的第一项,小的取出存入res
            left[0] < right[0] ? result.push(left.shift()) : result.push(right.shift());
          }
          return result.concat(left, right);
        }
    
    console.log(mergeSort(arr))
    // [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

    堆排序(Heap Sort)

    • 将初始待排序关键字序列 (R1, R2 .... Rn) 构建成大顶堆,此堆为初始的无序区;
    • 将堆顶元素 R[1] 与最后一个元素 R[n] 交换,此时得到新的无序区 (R1, R2, ..... Rn-1) 和新的有序区 (Rn) ,且满足 R[1, 2 ... n-1] <= R[n]。
    • 由于交换后新的堆顶 R[1] 可能违反堆的性质,因此需要对当前无序区 (R1, R2 ...... Rn-1) 调整为新堆,然后再次将 R[1] 与无序区最后一个元素交换,得到新的无序区 (R1, R2 .... Rn-2) 和新的有序区 (Rn-1, Rn)。不断重复此过程,直到有序区的元素个数为 n - 1,则整个排序过程完成。

      let arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48]
      // 堆排序
    const heapSort = array => {
        console.time('堆排序耗时');
        // 初始化大顶堆,从第一个非叶子结点开始
        for (let i = Math.floor(array.length / 2 - 1); i >= 0; i--) {
            heapify(array, i, array.length);
        }
        // 排序,每一次 for 循环找出一个当前最大值,数组长度减一
        for (let i = Math.floor(array.length - 1); i > 0; i--) {
            // 根节点与最后一个节点交换
            swap(array, 0, i);
            // 从根节点开始调整,并且最后一个结点已经为当前最大值,不需要再参与比较,所以第三个参数为 i,即比较到最后一个结点前一个即可
            heapify(array, 0, i);
        }
        console.timeEnd('堆排序耗时');
        return array;
    };
    
    // 交换两个节点
    const swap = (array, i, j) => {
        let temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    };
    
    // 将 i 结点以下的堆整理为大顶堆,注意这一步实现的基础实际上是:
    // 假设结点 i 以下的子堆已经是一个大顶堆,heapify 函数实现的
    // 功能是实际上是:找到 结点 i 在包括结点 i 的堆中的正确位置。
    // 后面将写一个 for 循环,从第一个非叶子结点开始,对每一个非叶子结点
    // 都执行 heapify 操作,所以就满足了结点 i 以下的子堆已经是一大顶堆
    const heapify = (array, i, length) => {
        let temp = array[i]; // 当前父节点
        // j < length 的目的是对结点 i 以下的结点全部做顺序调整
        for (let j = 2 * i + 1; j < length; j = 2 * j + 1) {
            temp = array[i]; // 将 array[i] 取出,整个过程相当于找到 array[i] 应处于的位置
            if (j + 1 < length && array[j] < array[j + 1]) {
                j++; // 找到两个孩子中较大的一个,再与父节点比较
            }
            if (temp < array[j]) {
                swap(array, i, j); // 如果父节点小于子节点:交换;否则跳出
                i = j; // 交换后,temp 的下标变为 j
            } else {
                break;
            }
        }
    };
    
    console.log(heapSort(arr))

     睡眠排序

    1. 当出现一个很大的数字,会睡眠很长时间(效率低)

    2. 当数字相差很小,会不精准(不精准)

    3. 不能处理负数(虽然可以在加上一个正数,再进行睡眠排序)

      let arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]
    
      var sleepSort = function (arr, callback) {
        let res = [];
        arr.forEach(item => {
          setTimeout(() => {
            res.push(item)
            // 如果执行完毕,回调
            if (res.length === arr.length) callback(res);
          }, item)
        });
      }
      sleepSort(arr, res => { console.log(res) })
  • 相关阅读:
    hdu 1159 Common Subsequence(最长公共子序列)
    Codeforces Round #313 (Div. 2)
    cf 558A Lala Land and Apple Trees
    zoj 2193 Window Pains
    poj 2031 Building a Space Station(最小生成树)
    zoj 1060 Sorting It All Out(拓扑排序)
    拓扑排序
    poj 1287 Networking
    zoj 1586 QS Network
    poj 1679 The Unique MST
  • 原文地址:https://www.cnblogs.com/gaoht/p/11400152.html
Copyright © 2020-2023  润新知