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;
}
相关文章
|
3天前
|
算法 JavaScript 前端开发
LZH 算法的模拟实现,JavaScript 版本
LZH 算法的模拟实现,JavaScript 版本
15 0
|
2天前
|
JavaScript 前端开发
Angular.js 应用中数据模式的删除操作实现
Angular.js 应用中数据模式的删除操作实现
15 0
|
3天前
|
移动开发 算法 前端开发
前端算法之堆排序
前端算法之堆排序
15 1
|
1天前
|
前端开发 JavaScript 算法
JavaScript 中实现常见数据结构:栈、队列与树
JavaScript 中实现常见数据结构:栈、队列与树
|
2天前
|
存储 JSON JavaScript
Node.js 上开发一个 HTTP 服务器,监听某个端口,接收 HTTP POST 请求并处理传入的数据
Node.js 上开发一个 HTTP 服务器,监听某个端口,接收 HTTP POST 请求并处理传入的数据
13 0
|
3天前
|
JavaScript 前端开发 算法
JavaScript的垃圾回收机制通过标记-清除算法自动管理内存
【5月更文挑战第11天】JavaScript的垃圾回收机制通过标记-清除算法自动管理内存,免除开发者处理内存泄漏问题。它从根对象开始遍历,标记活动对象,未标记的对象被视为垃圾并释放内存。优化技术包括分代收集和增量收集,以提升性能。然而,开发者仍需谨慎处理全局变量、闭包、定时器和DOM引用,防止内存泄漏,保证程序稳定性和性能。
17 0
|
3天前
|
算法 JavaScript 前端开发
三个js算法
三个js算法
8 2
|
3天前
|
算法 JavaScript
js的两个常用算法
js的两个常用算法
5 1
|
3天前
【数据结构】二叉树-堆(top-k问题,堆排序,时间复杂度)
【数据结构】二叉树-堆(top-k问题,堆排序,时间复杂度)
17 4
|
3天前
|
JavaScript 前端开发 算法
【JavaScript技术专栏】使用JavaScript实现常见算法
【4月更文挑战第30天】本文介绍了如何使用JavaScript实现常见算法,包括排序、搜索和图算法。首先,通过JavaScript的`sort`方法讨论了排序算法,以快速排序为例展示了自定义排序的实现。接着,探讨了二分查找这一高效的搜索算法,并提供了实现代码。最后,解释了深度优先搜索(DFS)图算法,并给出了在JavaScript中的实现。理解并运用这些算法能有效提升编程能力。