递归生成指定节点数目的树

主宰稳场 提交于 2020-02-26 10:14:45

做测试的时候需要用随机生成的树, 并且能指定节点个数

 

算法思路

一, 对一个数字进行分割

对数字N, 将其分割为最多M个数字之和

想象有N个小球排成一列, 有N-1个空挡, 随机找M-1个空挡放入挡板, 在第一个小球前面,  和最后一个小球后面也放上挡板, 这样就有了M+1个挡板, 相邻两个挡板之间的距离就是分离出来的树, 如果有两个挡板在同一位置, 说明, 分离出来的数字中含有0

 

二, 前序递归建树

对于递归函数而言, buildTree(n) 表示 返回有n个节点树, 则n===1时 直接返回一个节点, n>1 时表示该节点含有子树, 需要进行拆分后, 依次创建子节点, 由于采用前序生成, 所以前序遍历的id序列即为增序序列

function splitInt(n, count) {
  let list = [...Array(count - 1)]
    .map(_ => Math.floor(Math.random() * n))
    .sort((a, b) => a - b)

  list.push(n)
  list.unshift(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++)
    for (let i of childCount) {
      if (i < 1) continue
      root.child.push(buildTree(i))
    }
    return root
  }

  return buildTree(count)
}


let root = getTree(100, 16)
// console.log(root)

function getNodeNum(root) {
  let count = 0
  function dfs(r) {
    if (!r) return
    count++
    // console.log(r.id)
    for (let i of r.child)
      dfs(i)
  }
  dfs(root)
  return count
}
console.log(getNodeNum(root))

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!