堆是一個完全二叉樹,用js實現堆

堆和堆排序:爲什麼說堆排序沒有快速排序快?
堆排序交互數據次數比快排的多

堆:

  • 堆是一個完全二叉樹;
  • 堆中的每一個節點的值都必須大於等於(或小於等於)其子樹中每個節點的值。
    大頂堆,根節點最大
    小頂堆,跟節點最小
/*
 * @Author: HotSuitor
 * @Date: 2020-03-19 16:01:22
 * @LastEditors: hs
 * @LastEditTime: 2020-03-19 22:44:45
 * @Description: [email protected]
 */
// 堆
const heap = [undefined, 33, 27, 21, 16, 13, 15, 9, 5, 6, 7, 8, 1, 2];

class Heap {
  constructor(arr, size) {
    this.heapArray = arr || [];
    this.size = size + 1 || 300;
  }
  // 根節點索引=1,左子節點=2*i,右子節點=2*i+1, i=層數
  insert(data) {
    let len = this.heapArray.length;
    if (len >= this.size) {
      console.log("堆滿了");
      return; // 堆滿了
    }
    if (len === 0) {
      this.heapArray.splice(0, 0, undefined, data);
      return;
    }
    this.heapArray.push(data);
    let currentIndex = this.heapArray.length - 1;
    let i; // 層數,從0開始
    let parentIndex;
    //! 奇數->跟、右節點,偶數->左節點
    parentIndex = currentIndex % 2 ? (currentIndex - 1) / 2 : currentIndex / 2; // 父節點的索引
    // 自下往上堆化
    while (
      parentIndex > 0 &&
      this.heapArray[currentIndex] > this.heapArray[parentIndex]
    ) {
      this.swap(this.heapArray, currentIndex, parentIndex);
      currentIndex = parentIndex;
      parentIndex =
        currentIndex % 2 ? (currentIndex - 1) / 2 : currentIndex / 2; // 父節點的索引
    }
  }
  // 刪除堆頂元素
  deleteTop(data) {
    let len = this.heapArray.length;
    if (len <= 2) return this.heapArray;
    /**最後一個與第一個元素互換位置
     * 再自頂而下堆化
     */
    this.swap(this.heapArray, 1, len - 1);
    this.heapArray.pop();
    let i = 1;
    while (
      i * 2 < this.heapArray.length &&
      this.heapArray[i] < this.heapArray[i * 2]
    ) {
      this.swap(this.heapArray, i, i * 2);
      i = i * 2;
    }
  }
  scan() {
    return this.heapArray;
  }
  swap(arr, i, j) {
    let tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
  }
}

class Heap2 {
  constructor(capacity) {
    this.arr = new Array(capacity + 1); // 數組下標從1開始
    this.n = capacity; // 堆可以存儲的最大數據個數
    this.count = 0; // 堆中已存儲的數據個數
  }
  // 建堆
  static buildHeap(arr) {
    if (!Array.isArray(arr)) return;
    let n = arr.length - 1; // 堆元素個數
    // 從第i個節點開始從上往下堆化,子節點不需要比較,所以向下取整
    let i = Math.floor(n / 2);
    for (; i >= 1; --i) {
      Heap2.heapify(arr, n, i);
    }
    return arr;
  }
  static heapify(arr, n, i) {
    while (true) {
      let maxPox = i;
      // 左子節點比父節點大
      if (i * 2 <= n && arr[i] < arr[i * 2]) maxPox = i * 2;
      // 右節點比左節點大
      if (i * 2 + 1 <= n && arr[maxPox] < arr[i * 2 + 1]) maxPox = i * 2 + 1;
      if (maxPox === i) break;
      // 交互父子節點
      Heap2.swap(arr, i, maxPox);
      i = maxPox;
    }
  }
  insert(data) {
    if (this.count >= this.n) return; // 堆滿了
    this.count++;
    this.arr[this.count] = data;
    let i = this.count;
    // 自下而上堆化
    while (i / 2 > 0 && this.arr[i] > this.arr[i / 2]) {
      this.swap(this.arr, i, i / 2);
      i = i / 2;
    }
  }
  static deleteTop(arr) {
    if (arr.length <= 1) return;
    Heap2.swap(arr, 1, arr.length - 1);
    let result = arr.pop();
    let i = 1;
    while (true) {
      let maxPox = i;
      // 左節點
      if (i * 2 < arr.length && arr[i] < arr[i * 2]) maxPox = i * 2;
      if (i * 2 + 1 < arr.length && arr[maxPox] < arr[i * 2 + 1])
        maxPox = i * 2 + 1;
      if (maxPox === i) break;
      Heap2.swap(arr, i, maxPox);
      i = maxPox;
    }
    return result;
  }
  scan() {
    return this.arr;
  }
  static swap(arr, i, j) {
    let tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
  }
  swap(arr, i, j) {
    let tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
  }
  // 堆排序
  static sort(arr) {
    let i = arr.length - 1; // 排序的索引
    let result = new Array(arr.length);
    for (; i >= 1; i--) {
      let maxValue = Heap2.deleteTop(arr);
      result[i] = maxValue;
    }
    return result;
  }
}

// let heap2 = new Heap(heap);
// heap2.insert(22);
// heap2.insert(23);
// console.log(heap2.scan());
// heap2.deleteTop();
// heap2.deleteTop();
// console.log(heap2.scan());

// let heap3 = new Heap([], 5);
// heap3.insert(23);
// heap3.insert(27);
// heap3.insert(33);
// heap3.insert(45);
// heap3.insert(22);
// console.log(heap3.scan());
// heap3.deleteTop();
// console.log(heap3.scan());

// let heap4 = new Heap2(5);
// heap4.insert(33);
// heap4.insert(23);
// heap4.insert(45);
// heap4.insert(22);
// heap4.insert(7);
// console.log(heap4.scan());

let arr1 = [, 3, 44, 23, 18, 39, 26, 77];
let arr2 = [...arr1];
let arr1Heap = Heap2.buildHeap(arr2);
console.log("arr1", arr1);
console.log("arr1Heap", arr1Heap);
console.log("heapSort", Heap2.sort(arr1Heap));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章