最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React的小顶堆排序法

    正文概述 掘金(竹业)   2021-07-11   877

    前言

    想要了解react源码,还是得要了解一丢丢的算法,周末学习一个堆排序里面的小顶堆。

    为什么要了解堆排序,因为react17源码里任务优先级调度,采用的就是小顶堆。

    基础知识

    假如一个数组[1,2,3,4,5,6,7],生成二叉树的结构是什么样,就是下面的样子,小括号里面是对应数组的索引

    一个父节点有两个子节点,左边叫左子节点,右边叫右子节点

    其中数字1相当于2,3的父节点,2相当于4,5的父节点,3相当于6,7的父节点

    React的小顶堆排序法

    代码安排

    假如一个随机的数组arr1 = [3,6,4,9,2,1,7],里面是数代表着,不同的任务,对应的数字越小,代表优先级最高

    数组排列成小顶堆

    小顶堆:每一个父节点都比它的两个子节点小,第一个父节点是最小的

    • 每次push进去一个元素,和这个元素的索引
    • 找出这个子元素的父元素,然后比较大小,递归执行该方法,直到找到最上层第一个元素

    排列之后: React的小顶堆排序法

    排序

    排序的过程实际上也是react事件的调度的过程

    取出最顶端元素(优先级最高的任务去执行);最后一位元素,移动到第一位;再重新排序

    1.根据父节点的索引0,找出它的两个子节点

    2.父节点和左子节点比较

    • 左子节点小于父节点,再比较左子节点与右子节点
      • 右子节点小于左子节点,将右子节点与父节点互换,右子节点作为父节点,继续循环比较
      • 右子节点大于左子节点,将左子节点与父节点互换,左子节点作为父节点,继续循环比较
    • 左子节点大于父节点,比较右子节点与父节点
      • 右子节点小于父节点,将右子节点与父节点互换,右子节点作为父节点,继续循环比较
    var arr1 = [3,6,4,9,2,1,7];
    var heap = []  // 存排列好的小顶堆
    var stack = [] // 排序好的数组
    for(let i=0,len = arr1.length;i<len;i++) {
        const index = heap.length;
        const node =  arr1[i] 
        heap.push(node);
        siftUp(heap, node, index);
    }
    
    while(heap.length) {
        const first = heap[0]
        const last = heap.pop()
        stack.push(first)
        if(first !=last) {
            heap[0] = last;
            siftDown(heap, last, 0)
        } else {
            break;
        }
    }
        
    function siftDown(heap, node, i) {
        let index = i;
        const length = heap.length
        const halfLength = length >>> 1
        while(index < halfLength) {
           // 根据顶层父节点索引,找出它的左右子节点
           const leftIndex = (index + 1) * 2 - 1
           const left = heap[leftIndex]
           const rightIndex = leftIndex + 1
           const right = heap[rightIndex]
           // 左子节点小于父节点
           if (left < node) {
               // 右子节点小于左子节点,两个交换,右子节点作为父节点,继续循环
               if(rightIndex < length && right < left) {
                   heap[index] = right
                   heap[rightIndex] = node
                   index = rightIndex
               } else {
                   // 右子节点大于左子节点,两个交换,左子节点作为父节点,继续循环
                   heap[index] = left
                   heap[leftIndex] = node
                   index = leftIndex
               }
           } else if (rightIndex < length && right < node) {
               // 右子节点小于父节点,两个交换,右子节点作为父节点,继续循环
               heap[index] = right
               heap[rightIndex] = node
               index = rightIndex
           } else {
              return 
           }
        }
    }
        
    function siftUp(heap, node, i) {
        let index = i
        // 找到第一个元素,不再比较
        while(index > 0) {
            // 根据子节点索引,找到父节点
            const parentIndex = (index - 1) >>> 1
            const parent = heap[parentIndex]
            // 父节点大于子节点,父子节点交换位置
            if (parent > node) {
                heap[parentIndex] = node
                heap[index]= parent
                // 指针移动到父节点位置,作为子节点,找它的父节点
                index = parentIndex
            } else {
                return
            }
        }
    }
        
    

    总结

    堆也是一种数据类型,React的事件调度采用最小堆,非常经典的算法运用。空闲时间还是需要加强算法。

    感兴趣的小伙伴可以看看源码react/packages/scheduler/src/SchedulerMinHeap.js

    最后祝大家周末愉快,求点赞~


    起源地下载网 » React的小顶堆排序法

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元