堆数据结构与算法

91 阅读1分钟

堆数据结构,大根堆小根堆

/**

  • 大根堆特特点
  • 1.根节点大于左右子树的节点
  • 2.大根堆是一个完全二叉树
  • 大根堆父子节点之间的关系,对于节点i
  • 1.父节点:f=Math.floor((i-1)/2)
  • 2.左子节点:f=2*i+1
  • 3.右子节点:f=2*i+2 */
abstract class Heap {
  heap = [];
  constructor(heap: number[] = []) {
    this.heap = heap;
    for (let i = 1; i < heap.length; i++) {
      this.insertFromEnd(i);
    }
  }

  //插入
  insert(ele) {
    this.heap.push(ele);
    this.insertFromEnd(this.heap.length - 1);
  }

  //删除
  remove() {
    const res = this.heap[0];
    if (res === undefined) {
      return res;
    }
    if (this.heap.length === 1) {
      return this.heap.pop();
    }
    this.heap[0] = this.heap.pop();
    for (
      let i = 0, temp = 2 * i + 1;
      temp < this.heap.length;
      temp = 2 * i + 1
    ) {
      let nextI = temp;
      if (temp + 1 < this.heap.length && this.testFlag(temp + 1, temp)) {
        nextI = temp + 1;
      }
      if (this.testFlag(nextI, i)) {
        this.swap(i, nextI);
      } else {
        break;
      }
      i = nextI;
    }
    return res;
  }

  //从最后一个节点插入
  abstract insertFromEnd(i: number): void;

  abstract testFlag(i, j): boolean;

  //执行交换
  swap(i, j) {
    const temp = this.heap[i];
    this.heap[i] = this.heap[j];
    this.heap[j] = temp;
  }

  //获取栈顶元素
  getHeapTop() {
    return this.heap[0];
  }
}

class BigHeap extends Heap {
  constructor(array: number[] = []) {
    super([...array]);
    console.log(this);
  }

  testFlag(i, j) {
    return this.heap[i] > this.heap[j];
  }

  insertFromEnd(i) {
    for (
      let temp = Math.floor((i - 1) / 2);
      this.heap[i] > this.heap[temp];
      i = temp, temp = Math.floor((i - 1) / 2)
    ) {
      this.swap(i, temp);
    }
  }
}

class SmallHeap extends Heap {
  constructor(array: number[]) {
    super([...array]);
    console.log(this);
  }

  testFlag(i, j) {
    return this.heap[i] < this.heap[j];
  }

  insertFromEnd(i) {
    let pi = Math.floor((i - 1) / 2);
    while (this.heap[pi] > this.heap[i]) {
      this.swap(i, pi);
      i = pi;
      pi = Math.floor((i - 1) / 2);
    }
  }
}

利用堆解决问题

215. 数组中的第K个最大元素
function findKthLargest(nums: number[], k: number): number {
  const bigHeap = new BigHeap(nums);
  let i = 0;
  let res = -1;
  while (i < k) {
    res = bigHeap.remove();
    i++;
  }
  if (i === k) {
    return res;
  }
  return -1;
}
const res = findKthLargest([], 10);
求地k个丑数
function nthUglyNumber(n: number): number {
  if (n === 1) {
    return 1;
  }
  const set = new Set([1]);
  const smallHeap = new SmallHeap([1]);
  for (let i = 1; i < n; i++) {
    const sm = smallHeap.remove();
    for (let j = 2; j <= 5; j++) {
      const newItem = j * sm;
      if (!set.has(newItem)) {
        set.add(newItem);
        smallHeap.insert(newItem);
      }
    }
  }
  return smallHeap.remove();
}