跳至主要內容

树结构操作

Bing🐣代码笔记大约 2 分钟

树结构操作

遍历树结构

树结构
let tree = [
  {
    id: '1',
    title: '节点1',
    children: [
      {
        id: '1-1',
        title: '节点1-1'
      },
      {
        id: '1-2',
        title: '节点1-2'
      }
    ]
  },
  {
    id: '2',
    title: '节点2',
    children: [
      {
        id: '2-1',
        title: '节点2-1'
      }
    ]
  }
]

广度优先遍历

function treeForeach(tree, func, childrenName = 'children') {
  let node,
    list = [...tree]
  while ((node = list.shift())) {
    func(node)
    node[childrenName] && list.push(...node[childrenName])
  }
}

深度优先遍历

先序遍历
function treeForeach(tree, func) {
  tree.forEach((data) => {
    func(data)
    data.children && treeForeach(data.children, func) // 遍历子树
  })
}

深度优先循环

先序遍历
function treeForeach(tree, func) {
  let node,
    list = [...tree]
  while ((node = list.shift())) {
    func(node)
    node.children && list.unshift(...node.children)
  }
}

列表和树结构相互转换

列表转为树

list 数据
let list = [
  {
    id: '1',
    title: '节点1',
    parentId: ''
  },
  {
    id: '1-1',
    title: '节点1-1',
    parentId: '1'
  },
  {
    id: '1-2',
    title: '节点1-2',
    parentId: '1'
  },
  {
    id: '2',
    title: '节点2',
    parentId: ''
  },
  {
    id: '2-1',
    title: '节点2-1',
    parentId: '2'
  }
]
function listToTree(list) {
  let info = list.reduce(
    (map, node) => ((map[node.id] = node), (node.children = []), map),
    {}
  )
  return list.filter((node) => {
    info[node.parentId] && info[node.parentId].children.push(node)
    return !node.parentId
  })
}

树结构转列表

递归实现
function treeToList(tree, result = [], level = 0) {
  tree.forEach((node) => {
    result.push(node)
    node.level = level + 1
    node.children && treeToList(node.children, result, level + 1)
  })
  return result
}

树结构筛选

function treeFilter(tree, func) {
  // 使用map复制一下节点,避免修改到原树
  return tree
    .map((node) => ({ ...node }))
    .filter((node) => {
      node.children = node.children && treeFilter(node.children, func)
      return func(node) || (node.children && node.children.length)
    })
}

树结构查找

查找节点

function treeFind(tree, func) {
  for (const data of tree) {
    if (func(data)) return data
    if (data.children) {
      const res = treeFind(data.children, func)
      if (res) return res
    }
  }
  return null
}

查找节点路径

function treeFindPath(tree, func, path = []) {
  if (!tree) return []
  for (const data of tree) {
    path.push(data.id)
    if (func(data)) return path
    if (data.children) {
      const findChildren = treeFindPath(data.children, func, path)
      if (findChildren.length) return findChildren
    }
    path.pop()
  }
  return []
}

查找多条节点路径

function treeFindPath(tree, func, path = [], result = []) {
  for (const data of tree) {
    path.push(data.id)
    func(data) && result.push([...path])
    data.children && treeFindPath(data.children, func, path, result)
    path.pop()
  }
  return result
}