数据结构-堆

158 阅读1分钟
特点
  • 堆是一种特殊的完全二叉树。
  • 所有的节点都大于等于(最大堆)或小于等于(最小堆)的子节点;
  • 用数组表示最大堆;
  • 左侧子节点的位置是 2*index+1
  • 右侧子节点的位置事 2*index+2
  • 父节点的位置 index-1/2
操作

高效快速的找出最大值和最小值; 找出第K个最大的元素;

演示
class MinHeap {
  constructor() {
    this.heap = [];
  }
  swap(i1, i2) {
    const temp = this.heap[i1];
    this.heap[i1] = this.heap[i2];
    this.heap[i2] = temp;
  }
  getParentIndex(i) {
    return (i - 1) >> 1;
  }
  getLeftIndex(i) {
    return i * 2 + 1;
  }
  getRightIndex(i) {
    return i * 2 + 2;
  }
  shiftUp(index) {
    if (index == 0) {
      return;
    }
    const parentIndex = this.getParentIndex(index);
    if (this.heap[parentIndex] > this.heap[index]) {
      this.swap(parentIndex, index);
      this.shiftUp(parentIndex);
    }
  }
  shiftDown(index) {
    const leftIndex = this.getLeftIndex(index);
    const rightIndex = this.getRightIndex(index);
    if (this.heap[leftIndex] < this.heap[index]) {
      this.swap(leftIndex, index);
      this.shiftDown(leftIndex);
    }
    if (this.heap[rightIndex] < this.heap[index]) {
      this.swap(rightIndex, index);
      this.shiftDown(rightIndex);
    }
  }
  insert(value) {
    this.heap.push(value);
    this.shiftUp(this.heap.length - 1);
  }
  pop() {
    this.heap[0] = this.heap.pop();
    this.shiftDown(0);
  }
  peek() {
    return this.heap[0];
  }
  size() {
    return this.heap.length;
  }
}
练习题

215. 数组中的第K个最大元素

// 第k个最大元素,使用最小堆;
// 构建一个最小的堆,并依次将数组的值插入到堆中。 当堆得容量超过K,就删除堆顶; 插入结束后堆顶就是第k个最大元素
 var findKthLargest = function (nums, k) {
   const min = new MinHeap(); // 构建最小堆
   nums.forEach((item) => {
     min.insert(item);
     if (min.size() > k) { // 容量超出了,删除栈顶
       min.pop();
     }
   });
   return min.peek(); // 返回栈顶
 };

347. 前 K 个高频元素

var topKFrequent = function (nums, k) {
  const map = new Map();
  nums.forEach((i) => {
    map.set(i, map.has(i) ? map.get(i) + 1 : 1);
  });
  const list = Array.from(map).sort((a, b) => b[1] - a[1]);
  return list.slice(0, k).map((item) => item[0]);
};
 class MinHeap {
        constructor() {
          this.heap = [];
        }
        swap(i1, i2) {
          const temp = this.heap[i1];
          this.heap[i1] = this.heap[i2];
          this.heap[i2] = temp;
        }
        getParentIndex(i) {
          return (i - 1) >> 1;
        }
        getLeftIndex(i) {
          return i * 2 + 1;
        }
        getRightIndex(i) {
          return i * 2 + 2;
        }
        shiftUp(index) {
          if (index == 0) {
            return;
          }
          const parentIndex = this.getParentIndex(index);
          if (
            this.heap[parentIndex] &&
            this.heap[parentIndex].value > this.heap[index].value
          ) {
            this.swap(parentIndex, index);
            this.shiftUp(parentIndex);
          }
        }
        shiftDown(index) {
          const leftIndex = this.getLeftIndex(index);
          const rightIndex = this.getRightIndex(index);
          if (
            this.heap[leftIndex] &&
            this.heap[leftIndex].value < this.heap[index].value
          ) {
            this.swap(leftIndex, index);
            this.shiftDown(leftIndex);
          }
          if (
            this.heap[rightIndex] &&
            this.heap[rightIndex].value < this.heap[index].value
          ) {
            this.swap(rightIndex, index);
            this.shiftDown(rightIndex);
          }
        }
        insert(value) {
          this.heap.push(value);
          this.shiftUp(this.heap.length - 1);
        }
        pop() {
          this.heap[0] = this.heap.pop();
          this.shiftDown(0);
        }
        peek() {
          return this.heap[0];
        }
        size() {
          return this.heap.length;
        }
      }
 var topKFrequent = function (nums, k) {
   const map = new Map();
   nums.forEach((item) => {
     map.set(item, map.has(item) ? map.get(item) + 1 : 1);
   });
   const min = new MinHeap();
   map.forEach((value, key) => {
     min.insert({ key, value });
     if (min.size() > k) {
       min.pop();
     }
   });
   return min.heap.slice(0, k).map((item) => item.key);
 };

23. 合并K个升序链表

// 构建最小堆
 class MinHeap {
        constructor() {
          this.heap = [];
        }
        swap(i1, i2) {
          const temp = this.heap[i1];
          this.heap[i1] = this.heap[i2];
          this.heap[i2] = temp;
        }
        getParentIndex(i) {
          return (i - 1) >> 1;
        }
        getLeftIndex(i) {
          return i * 2 + 1;
        }
        getRightIndex(i) {
          return i * 2 + 2;
        }
        shiftUp(index) {
          if (index == 0) {
            return;
          }
          const parentIndex = this.getParentIndex(index);
          if (
            this.heap[parentIndex] &&
            this.heap[parentIndex].val > this.heap[index].val
          ) {
            this.swap(parentIndex, index);
            this.shiftUp(parentIndex);
          }
        }
        shiftDown(index) {
          const leftIndex = this.getLeftIndex(index);
          const rightIndex = this.getRightIndex(index);
          if (
            this.heap[leftIndex] &&
            this.heap[leftIndex].val < this.heap[index].val
          ) {
            this.swap(leftIndex, index);
            this.shiftDown(leftIndex);
          }
          if (
            this.heap[rightIndex] &&
            this.heap[rightIndex].val < this.heap[index].val
          ) {
            this.swap(rightIndex, index);
            this.shiftDown(rightIndex);
          }
        }
        insert(value) {
          this.heap.push(value);
          this.shiftUp(this.heap.length - 1);
        }
        pop() {
          if (this.size() === 1) return this.heap.shift();
          const top = this.heap[0];
          this.heap[0] = this.heap.pop();
          this.shiftDown(0);
          return top;
        }
        peek() {
          return this.heap[0];
        }
        size() {
          return this.heap.length;
        }
      }
 var mergeKLists = function (lists) {
   const res = new ListNode(0);
   const heap = new MinHeap();
   let p = res;
   lists.forEach((item) => {
     if (item) heap.insert(item);
   });
   while (heap.size()) {
     const node = heap.pop();
     p.next = node;
     p = p.next;
     if (node.next) heap.insert(node.next);
   }
   return res.next;
 };