JavaScript 数据结构与算法 之 二叉堆和堆排序

简介: JavaScript 数据结构与算法 之 二叉堆和堆排序

二叉堆和堆排序

二叉堆是计算机科学中一种非常著名的数据结构(一种特殊的二叉树),由于它能高效、快速地找出最大值和最小值,常被应用于优先队列。它也被用于著名的堆排序算法中。

数据结构

特性

  • 结构特性:它是一棵完全二叉树,表示树的每一层都有左侧和右侧子节点(除了最后一层的叶节点),并且最后一层的叶节点尽可能都是左侧子节点
  • 堆特性:二叉堆不是最小堆就是最大堆

    • 最小堆允许你快速导出树的最小值,最大堆允许你快速导出树的最大值
    • 所有的节点都大于等于(最大堆)或小于等于(最小堆)每个它的子节点
function swap(arr, a, b) {
  const temp = arr[a];
  arr[a] = arr[b];
  arr[b] = temp;
}
class MinHeap {
  constructor(compareFn = defaultCompare) {
    this.compareFn = compareFn;
    this.heap = [];
  }
  getLeftIndex(index) {
    return 2 * index + 1;
  }
  getRightIndex(index) {
    return 2 * index + 2;
  }
  getParentIndex(index) {
    if (index === 0) {
      return undefined;
    }
    return Math.floor((index - 1) / 2);
  }
  insert(value) {
    if (value != null) {
      this.heap.push(value);
      this.siftUp(this.heap.length - 1);
      return true;
    }
    return false;
  }
  siftUp(index) {
    let parent = this.getParentIndex(index);
    while (index > 0 &&
      this.compareFn(this.heap[parent], this.heap[index]) > Compare.BIGGER_THAN) {
      swap(this.heap, parent, index);
      index = parent;
      parent = this.getParentIndex(index);
    }
  }
  size() {
    return this.heap.length;
  }
  isEmpty() {
    return this.size() === 0;
  }
  findMinimum() {
    return this.isEmpty() ? undefined : this.heap[0];
  }
  extract() {
    if (this.isEmpty()) {
      return undefined;
    }
    if (this.size() === 1) {
      return this.heap.shift();
    }
    const removedValue = this.heap.shift();
    this.sifDown(0);
    return removedValue;
  }
  sifDown(index) {
    let element = index;
    const left = this.getLeftIndex(index);
    const right = this.getRightIndex(index);
    const size = this.size();
    if (left < size &&
      this.compareFn(this.heap[element], this.heap[left]) > Compare.BIGGER_THAN) {
        element = left;
    }
    if (right < size &&
      this.compareFn(this.heap[element], this.heap[right]) > Compare.BIGGER_THAN) {
        element = right;
    }
    if (index !== element) {
      swap(this.heap, index, element);
      this.sifDown(element);
    }
  }
}
function reverseCompare(compareFn) {
  return (a, b) => compareFn(b, a);
}
class MaxHeap extends MinHeap {
  constructor(compareFn = defaultCompare) {
    super(compareFn);
    this.compareFn = reverseCompare(compareFn);
  }
}

堆排序

思路

  1. 用数组创建一个最大堆用作源数据
  2. 在创建最大堆后,最大的值会被存储在堆的第一个位置,我们要将它替换为堆的最后一个值,将堆的大小减 1
  3. 最后,我们将堆的根节点下移并重复步骤 2 直到堆的大小为 1
function heapSort(array, compareFn = defaultCompare) {
  let heapSize = array.length;
  buildMaxHeap(array, compareFn);
  while (heapSize > 1) {
    swap(array, 0, --heapSize);
    heapify(array, 0, heapSize, compareFn);
  }
  return array;
}
function buildMaxHeap(array, compareFn) {
  for (let i = Math.floor(array.length / 2); i >= 0; i -= 1) {
    heapify(array, i, array.length, compareFn);
  }
  return array;
}
相关文章
|
1月前
|
JavaScript 前端开发
js实现数据的双向绑定
js实现数据的双向绑定
30 2
|
25天前
|
JavaScript 算法 前端开发
采招网JS逆向:基于AES解密网络数据
采招网JS逆向:基于AES解密网络数据
37 0
|
22天前
|
JavaScript 算法 前端开发
JS算法必备之String常用操作方法
这篇文章详细介绍了JavaScript中字符串的基本操作,包括创建字符串、访问特定字符、字符串的拼接、位置查找、大小写转换、模式匹配、以及字符串的迭代和格式化等方法。
JS算法必备之String常用操作方法
|
22天前
|
JavaScript 算法 前端开发
JS算法必备之Array常用操作方法
这篇文章详细介绍了JavaScript中数组的创建、检测、转换、排序、操作方法以及迭代方法等,提供了数组操作的全面指南。
JS算法必备之Array常用操作方法
|
1月前
|
数据采集 存储 JavaScript
基于Python 爬书旗网小说数据并可视化,通过js逆向对抗网站反爬,想爬啥就爬啥
本文介绍了如何使用Python编写网络爬虫程序爬取书旗网上的小说数据,并通过逆向工程对抗网站的反爬机制,最后对采集的数据进行可视化分析。
基于Python 爬书旗网小说数据并可视化,通过js逆向对抗网站反爬,想爬啥就爬啥
|
28天前
|
JSON JavaScript 数据格式
js实现更新数据
js实现更新数据
36 1
|
1月前
|
JavaScript 算法 前端开发
"揭秘Vue.js的高效渲染秘诀:深度解析Diff算法如何让前端开发快人一步"
【8月更文挑战第20天】Vue.js是一款备受欢迎的前端框架,以其声明式的响应式数据绑定和组件化开发著称。在Vue中,Diff算法是核心之一,它高效计算虚拟DOM更新时所需的最小实际DOM变更,确保界面快速准确更新。算法通过比较新旧虚拟DOM树的同层级节点,递归检查子节点,并利用`key`属性优化列表更新。虽然存在局限性,如难以处理跨层级节点移动,但Diff算法仍是Vue高效更新机制的关键,帮助开发者构建高性能Web应用。
39 1
|
1月前
|
前端开发 JavaScript 安全
JavaScript——数字超过精度导致数据有误
JavaScript——数字超过精度导致数据有误
28 2
|
1月前
|
JavaScript 前端开发
JavaScript中通过按回车键进行数据的录入
这篇文章提供了一个JavaScript示例代码,演示了如何通过监听回车键(keyCode为13)在网页上实现数据的录入和触发一个警告框提示"正在登录验证......"。
JavaScript中通过按回车键进行数据的录入
|
1月前
|
JavaScript 数据处理
如何使用 Vue.js 将数据对象的值放入另一个数据对象中?
如何使用 Vue.js 将数据对象的值放入另一个数据对象中?