React源码系列--调度算法-最小堆

57 阅读3分钟

准备开一个React系列,主要是记录和复习学习React源码,因为确实很容易忘记

目前打算从调度算法开始这个系列,个人认为在学习调度算法之前最好了解一下最小堆,所以先写一个关于最小堆的介绍,以便后边的理解

最小堆前置知识

在了解最小堆之前,有必要先了解二叉树

二叉树:

二叉树是树种的每一个节点的子节点个数都小于等于2的树 二叉树又分为两种:满二叉树完全二叉树

满二叉树:

如果一棵二叉树只有度为0的节点和度为2的节点,并且节点为0的节点都在同一层,则称为满二叉树

完全二叉树:

除了最低层外,每一层都已经填满,并且最下面一层的节点都集中在最左边的位置(只有右边存在连续的空位) 其下标满足规律:parentIndex = (childIndex - 1) >>> 1leftIndex = (index +1 )*2 - 1rightIndex = leftIndex + 1
堆其实是一棵完全二叉树,同时保证父子节点的顺序关系

最小堆

最小堆是一个经过排序的完全二叉树,其任一非终端节点的数值都不大于其左右节点 根据上边发现的完全二叉树的下标规律,那我们可以尝试完成最小堆的增删查

获取最小堆的堆顶值

function peek<T>(heap:Heap<T>):T|null{
  return heap.length>0?heap[0]:null;
}

添加

往最小堆中添加元素,一般是将新元素插入数组的尾部,然后从堆低向上调整

怎么调整呢?

最小堆的特点就是父节点比左右两个节点都小,那我们现在最多只有最末尾新增的元素不满足,那我们就一直判断,然后向上调整就可以了

function push<T>(heap: Heap<T>, node: T):void{
  let index = heap.length;
  heap.push(node);
  while (index > 0) {
    const parentIndex = Math.floor((index - 1) / 2);
    if (heap[parentIndex] <= heap[index]) break;
    [heap[parentIndex], heap[index]] = [heap[index], heap[parentIndex]];
    index = parentIndex;
  }
}

删除堆顶元素

当React执行完某一个任务时候,将该任务从队列中删除,即将队列的第一个元素删除

那怎么调整呢?

我们可以将最末尾的元素提到堆顶,然后从堆顶向下调整,原理呢和上面差不多,都是要抓住最小堆的重要特征父节点比左右两个节点都小

function pop<T>(heap:Heap<T>): T | null {
  if (heap.length === 0) return null;

  const root = heap[0];
  const last = heap.pop();

  if (heap.length > 0 && last !== undefined) {
    heap[0] = last;
    siftDown(heap, 0);
  }
  return root;
}

  

function siftDown<T>(heap:Heap<T>, index:number) {
  const leftChildIndex = 2 * index + 1;
  const rightChildIndex = 2 * index + 2;
  let smallestIndex = index;

  if (leftChildIndex < heap.length && heap[leftChildIndex] < heap[smallestIndex]) {
    smallestIndex = leftChildIndex;
  }
  
  if (rightChildIndex < heap.length && heap[rightChildIndex] < heap[smallestIndex]) {
    smallestIndex = rightChildIndex;
  }
  
  if (smallestIndex !== index) {
    [heap[index], heap[smallestIndex]] = [heap[smallestIndex], heap[index]];
    siftDown(heap, smallestIndex);
  }
  return;
}

关于调度算法中涉及的最小堆部分也差不多了,那我们下一节再见 希望本文对您有所帮助,如果有任何错误,欢迎指出,十分感谢💖💖💖