地址树数据查找

链表式节点数据查找,与地址树数据算法

伪树

  • 已知后端数据结构如下,要求只返回最里面的id=8,获得最里面那个节点,用name组织的节点路径
  • root/北京市/西城区/xx居委会
let root = [
    id: 5,
    name: "root",
    children: [{
        id: 6,
        name: "北京市",
        children: [{
            id: 7,
            name: "西城区",
            children: [{
                id: 8,
                name: "xx居委会"
            }]
        }]
    }]
]

思路

  1. 循环节点,发现子节点,则变更节点指针位置指向一个节点
  2. 为避免死循环,使用计时变量i 及匹配条件跳出
  3. 上述源数据实为一个单链表,每个节点只有一个子节点

代码

此法适合单链表,即只有一个前驱后继的情况查找
示例查找 id 为8 的路径


let i = 1
let res = []
let searchId = 8
levelNode.children = root
while (true && i < 50) {
  if (levelNode.children) {
    levelNode = levelNode.children[0]
  }
  // 记录查找路径,由于id是唯一,故从根到指定id的路径是唯一
  // 当前层路径查找
  res.push(levelNode.name)

  // 找到退出 
  levelNode.id == searchId && break
  i++
}

console.log(res)

问题

上述结构,若某个节点存在多个子节点,在非同辈节点的首位节点查找则会出错
因此对下面源数据比如id为7,8,9会无能为力

 [{
  id: 5,
  name: "root",
  children: [{
    id: 6,
    name: "北京市",
    children: [{
      id: 10,
      name: "东城区"
    },
    {
      id: 7,
      name: "西城区",
      children: [
        {
          id: 8,
          name: "xx居委会"
        },
        {
          id: 9,
          name: 'xx街道'
        }]
    }]
  }]
}]

分析

  1. 叶子节点直接返回 id
  2. 同辈节点遍历
  3. 发现有孩子的直接交给内层函数处理,其返回的是内层值
  4. 将根节点包装成无父无标识的子组,否则根,需自行找补

关键分清当前域环境下的节点,与子节点环境的指向
叶子节点直接处理,指向子节点组交给内层循环处理
递归遍历,解包

方案

为便于直观过滤,将返回指定id所经过的路径节点列表

function queryPathByID(nd, id) {
  for (let i = nd.children.length - 1; i >= 0; i--) {
    const e = nd.children[i];
    // 2.进入下一级
    if (e.children) {
      // 3. 移动指针进入 当前节点+下一层节点
      return [e.id, ...queryPathByID(e, id)]
    } else if (e.id == id) {
      // 4. 叶子节点元素
      return [e.id]
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值