fiber 遍历方式比较

原文链接: fiber 遍历方式比较

上一篇: react fiber 遍历方式简单实现

下一篇: 使用生成器模拟时间分片

对比递归和fiber链表式遍历方式的速度

fiber综合上能快一倍

up-86acc129763ce15e2c103412a96802d9503.png

function splitInt(n, count) {
  if (n < 2) return [n]
  let list = [...Array(count - 1)]
    .map(i => parseInt(Math.random() * n))
    .sort((a, b) => a - b)
  list.push(n)
  list.unshift(0)
  // console.log(list.filter(i => i < 0))
  let res = []
  for (let i = 1; i <= count; i++) {
    res.push(list[i] - list[i - 1])
  }
  return res
}

class Node {
  constructor(id, child = []) {
    this.id = id
    this.child = child
  }
}

function getTree(count, maxChild = 16) {
  let id = 0

  // 创建n个节点的树
  function buildTree(n) {
    if (n === 1) return new Node(id++)
    let childCount = splitInt(n - 1, maxChild)
    let root = new Node(id++)
    // console.log('n', n, childCount)
    for (let i of childCount) {
      if (i < 1) continue
      root.child.push(buildTree(i))
    }
    return root
  }

  return buildTree(count)
}


class FNode {
  constructor(id, sibling, parent, child = []) {
    this.id = id
    this.parent = parent
    this.child = child
    this.sibling = sibling
  }
}


function getNodeNum(root) {
  let count = 0

  function dfs(r) {
    if (!r) return
    count++
    for (let i of r.child)
      dfs(i)
  }

  dfs(root)
  return count
}

function tree2fiber(tree) {
  let root = new FNode(tree.id)
  let nodes = tree.child
  let preNode = null
  for (let i = 0; i < nodes.length; i++) {
    let node = tree2fiber(nodes[i])
    node.parent = root
    if (i === nodes.length - 1) {
      node.sibling = null
      // preNode.sibling = node
    }
    preNode && (preNode.sibling = node)
    preNode = node
    root.child.push(node)
  }
  return root
}

// 返回字符串
function recursion(root) {
  let res = []

  function dfs(r) {
    if (!r) return
    res.push(r.id)
    for (let i of r.child)
      dfs(i)
  }

  dfs(root)
  return res
}


// 返回字符串
function fiber(root) {
  let res = []
  let current = root
  while (true) {
    res.push(current.id)
    if (current.child.length) {
      current = current.child[0]
      continue
    }
    if (current === root) {
      break
    }

    while (!current.sibling) {
      // 如果我们回到了根节点,退出函数
      if (!current.parent || current.parent === root) {
        return res;
      }
      // 设置父节点为当前活跃节点
      current = current.parent;
    }
    current = current.sibling
  }
  return res
}


let time1 = []
let time2 = []
let countList = []
for (let pow = 1; pow < 100; pow++) {
  let testCount = 100
  let COUNT = 1000 * pow
  countList.push(COUNT)
  let sum1 = 0
  let sum2 = 0
  for (let i = 0; i < testCount; i++) {
    let root = getTree(COUNT, 16)
    // console.log(getNodeNum(root))
    // let root = getBinTree(COUNT)
    let fiberLink = tree2fiber(root)
    let st2 = +new Date()
    let dfsRes = recursion(root)
    let ed2 = +new Date()
    let st1 = +new Date()
    let fiberRes = fiber(fiberLink)
    let ed1 = +new Date()
    // console.log('fiber', ed1 - st1, 'dfs', ed2 - st2, fiberRes.join('') === dfsRes.join(''))
    // console.log(getNodeNum(root), fiberRes.length)
    // console.log(dfsRes.join(','))
    // time1.push(ed1 - st1)
    // time2.push(ed2 - st2)
    sum1 += (ed1 - st1)
    sum2 += (ed2 - st2)
  }
  time1.push(sum1 / testCount)
  time2.push(sum2 / testCount)
}

console.log(time1.join(','))
console.log(time2.join(','))
console.log(countList.join(','))
// 二叉树
// 0.09,0.1,0.18,0.14,0.22,0.46,0.43,0.44,0.45,0.51,0.71,0.69,0.96,0.74,0.94,1.09,1.12,1.21,1.32,1.35,1.33,1.53,1.92,1.69,1.98,2.09,2.01,2.11,2.11,2.22,2.27,2.23,2.44,2.62,2.62,3.13,2.72,2.9,2.66,2.68,2.87,2.74,2.71,3.05,2.99,2.97,3.09,3.21,3.19,3.33,3.83,3.87,3.88,3.96,4.16,4.25,4.36,4.12,4.41,4.3,4.49,4.42,4.65,4.68,4.9,4.9,4.76,4.96,4.93,4.91,5.4,5.2,5.04,5.16,5.36,5.58,5.95,5.97,6.09,5.99,6.05,5.99,6.06,6.24,6.43,6.37,6.31,6.31,6.35,6.44,6.58,6.6,6.81,6.76,6.8,6.94,6.95,6.85,7
// 0.07,0.15,0.2,0.3,0.24,0.36,0.44,0.33,0.56,0.62,0.41,0.95,0.87,1.19,1.2,1.55,1.37,1.56,1.48,2,2.21,1.89,2.52,2.69,3.26,2.85,3.44,3.98,3.78,3.72,4,4.15,4.37,4.84,5.02,5.45,5.96,6.28,7.2,7.19,7.66,7.66,7.59,8.61,8.28,8.32,8.42,7.84,7.7,7.66,8.81,8.01,8.19,7.72,7.91,7.86,7.48,7.41,8.23,7.99,8.18,8.7,9.15,9.26,7.28,8.85,8.69,8.53,8.95,9.1,9.35,9.83,9.88,10.03,10.07,10.22,11.1,10.94,11.48,11.51,11.77,11.7,11.55,11.83,11.8,12.32,12.12,12.4,11.25,10.83,12.45,12.09,13.48,12.51,12.13,12.3,13.63,12.78,12.13

// 随机树
// 0.03,0.08,0.06,0.09,0.16,0.11,0.12,0.29,0.2,0.22,0.33,0.35,0.39,0.43,0.35,0.74,0.68,0.67,0.61,0.77,0.72,0.69,0.88,1.06,1.09,1.03,1.17,1.03,1.24,1.03,1.04,1.11,1.58,1.55,1.53,1.64,1.61,1.63,1.58,1.59,1.78,1.73,1.72,1.98,1.76,1.74,1.65,1.86,1.86,2,2.36,2.31,2.41,2.36,2.36,2.55,2.34,2.92,2.69,2.71,2.58,2.76,2.97,2.85,2.54,2.97,3.15,3,3,3.02,2.99,3.07,2.99,3.24,3.02,3.26,3.76,3.97,3.54,3.77,5.12,3.98,4.05,4.14,4.2,4.05,4.14,5.12,4.39,4.32,4.33,4.45,4.32,4.8,5.84,5.34,4.72,4.47,4.83
// 0.06,0.11,0.16,0.24,0.28,0.26,0.34,0.31,0.47,0.43,0.65,0.63,0.81,0.65,0.69,0.99,0.96,1.07,0.9,1.02,1.24,1.32,1.42,1.47,1.56,1.61,1.69,1.7,1.59,1.92,1.89,1.99,2.02,2.36,2.42,2.88,2.43,2.38,2.62,2.63,2.54,2.52,2.59,2.95,2.83,2.91,2.95,2.76,2.94,2.97,3.53,3.55,4.03,3.48,3.58,3.41,3.53,3.71,3.88,3.59,3.68,3.91,3.91,3.83,4.14,4.14,4.08,4.3,4.24,4.41,4.17,4.24,4.72,4.73,4.45,4.39,5.36,5.07,6.06,5.08,6.49,5.33,5.3,5.28,5.41,5.81,5.67,5.71,5.67,5.78,5.52,5.61,5.68,6.01,6.09,6.2,6.7,6.84,7.14
// 1000,2000,3000,4000,5000,6000,7000,8000,9000,10000,11000,12000,13000,14000,15000,16000,17000,18000,19000,20000,21000,22000,23000,24000,25000,26000,27000,28000,29000,30000,31000,32000,33000,34000,35000,36000,37000,38000,39000,40000,41000,42000,43000,44000,45000,46000,47000,48000,49000,50000,51000,52000,53000,54000,55000,56000,57000,58000,59000,60000,61000,62000,63000,64000,65000,66000,67000,68000,69000,70000,71000,72000,73000,74000,75000,76000,77000,78000,79000,80000,81000,82000,83000,84000,85000,86000,87000,88000,89000,90000,91000,92000,93000,94000,95000,96000,97000,98000,99000

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值