阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      JavaScript 堆排序

      堆排序

      堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行 交换,此时末尾就为最大值。然后将剩余 n-1 个元素重新构造成一个堆,这样会得到 n 个元素的次小值。如此反复执行, 便能得到一个有序序列了。

      function heapSort(array) {
      
        let length = array.length;
      
        // 如果不是数组或者数组长度小于等于1,直接返回,不需要排序 
        if (!Array.isArray(array) || length <= 1) return;
      
        buildMaxHeap(array); // 将传入的数组建立为大顶堆
      
        // 每次循环,将最大的元素与末尾元素交换,然后剩下的元素重新构建为大顶堆
        for (let i = length - 1; i > 0; i--) {
          swap(array, 0, i);
          adjustMaxHeap(array, 0, i); // 将剩下的元素重新构建为大顶堆
        }
      
        return array;
      }
      
      
      function adjustMaxHeap(array, index, heapSize) {
        let iMax,
          iLeft,
          iRight;
      
        while (true) {
          iMax = index; // 保存最大值的索引
          iLeft = 2 * index + 1; // 获取左子元素的索引
          iRight = 2 * index + 2; // 获取右子元素的索引
      
          // 如果左子元素存在,且左子元素大于最大值,则更新最大值索引
          if (iLeft < heapSize && array[iMax] < array[iLeft]) {
            iMax = iLeft;
          }
      
          // 如果右子元素存在,且右子元素大于最大值,则更新最大值索引
          if (iRight < heapSize && array[iMax] < array[iRight]) {
            iMax = iRight;
          }
      
          // 如果最大元素被更新了,则交换位置,使父节点大于它的子节点,同时将索引值跟新为被替换的值,继续检查它的子树
          if (iMax !== index) {
            swap(array, index, iMax);
            index = iMax;
          } else {
      
            // 如果未被更新,说明该子树满足大顶堆的要求,退出循环
            break;
          }
        }
      }
      
      // 构建大顶堆
      function buildMaxHeap(array) {
        let length = array.length,
          iParent = parseInt(length >> 1) - 1; // 获取最后一个非叶子点的元素
      
        for (let i = iParent; i >= 0; i--) {
          adjustMaxHeap(array, i, length); // 循环调整每一个子树,使其满足大顶堆的要求
        }
      }
      
      // 交换数组中两个元素的位置
      function swap(array, i, j) {
        let temp = array[i];
        array[i] = array[j];
        array[j] = temp;
      }
      

      建立堆的时间复杂度为 O(n),排序循环的次数为 n-1,每次调整堆的时间复杂度为 O(logn),因此堆排序的时间复杂度在 不管什么情况下都是 O(nlogn)。

      堆排序的平均时间复杂度为 O(nlogn) ,最坏时间复杂度为 O(nlogn) ,空间复杂度为 O(1) ,不是稳定排序。

      详细资料可以参考: 《图解排序算法(三)之堆排序》 《常见排序算法 - 堆排序 (Heap Sort)》 《堆排序中建堆过程时间复杂度O(n)怎么来的?》 《排序算法之 堆排序 及其时间复杂度和空间复杂度》 《最小堆 构建、插入、删除的过程图解》

      更多面试题

      如果你想了解更多的前端面试题,可以查看本站的WEB前端面试题 ,这里基本包涵了市场上的所有前端方面的面试题,也有一些大公司的面试图,可以让你面试更加顺利。

      面试题
      HTMLCSSJavaScript
      jQueryVue.jsReact
      算法HTTPBabel
      BootStrapElectronGulp
      Node.js前端经验相关前端综合
      Webpack微信小程序-

      这些题库还在更新中,如果你有不错的面试题库欢迎分享给我,我整理后放上来;人人为我,我为人人,互帮互助,共同提高,祝大家都拿到心仪的Offer!

      目录
      目录