微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Javascript - 遍历一棵树以生成节点的序列

如何解决Javascript - 遍历一棵树以生成节点的序列

我发现很少有与此相关的 SO 问题,但没有一个是基于我试图解决的确切问题。

基本上,我正在研究一个树结构,每个节点都分配了一个 id。

目标是生成一个序列字符串,该字符串将提供顺序遍历整个树的路径。

例如下图的输出应该是123242523637321


enter image description here


如您所见,树从节点 1 开始,然后到达节点 2。

节点 2 连接到其他 3 个节点,即。节点 3、节点 4 和节点 5。

按照顺序,下一个节点是3。

要转到下一个节点,即节点 4,我们必须返回节点 2,然后再转到节点 4,因此字符串变为 12324

一旦我们得到最后一个节点,即节点 7,我们将返回到第一个节点,因此字符串以子字符串 7321

结束

我正在尝试构建一个逻辑,从给定的树结构生成字符串

上图的示例树结构是 -


const sequenceObj = {
    1: {
        id: "Point_1cec2262-20f8-4985-adcb-b6d95a618d22",connectednodes: ["2"]
    },2: {
        id: "Point_02bdae16-1cdb-48e1-a601-7b1e526eedb8",connectednodes: ["1","3","4","5"]
    },3: {
        id: "Point_55a68ac0-17ef-48a2-bf9f-c70004a27d99",connectednodes: ["2","6","7"]
    },4: {
        id: "Point_8760427c-98bb-4e3e-85dd-59cba3b31c6f",5: {
        id: "Point_79a7bcec-d110-43dc-b9ac-1552538bc1a5",6: {
        id: "Point_37550cf0-4bd5-48b2-b32f-9018bd55c05f",connectednodes: ["3"]
    },7: {
        id: "Point_2de67998-9e1f-4b06-af18-77d558d68254",connectednodes: ["3"]
    }
};

如您所见,每个节点都有一个名为 connectednodes 的属性,可帮助我们遍历树。


编辑 - 正如评论中所指出的,属性 connectednodes以前称为 children)存储连接节点的 id。 提供的对象不代表树,我们只需要使用这个对象从头到尾遍历,即在这个例子中从id 1到7。


如果我遗漏了什么或需要更多信息,请告诉我。

谢谢!

解决方法

您的输入写在一个节点中,将它们的父节点列为 export const RegisterWithEmail = async user => { console.log("Called Once..."); if(!user) return 'SOMETHING_WENT_WRONG'; else { const snap = await firestore.collection('users').where('email','==',user.email).get(); const docs = snap.docs.map((doc) => doc.data()); if (docs.length !== 0) return 'EMAIL_HAS_ALREADY_BEEN_TAKEN'; try { console.log("Trying to register email..."); return await auth.createUserWithEmailAndPassword(user.email,user.password).then(async usr => { await usr.user.updateProfile({ displayName: user.name }) // SETTING NAME const sendVerifyEmail = usr.user.sendEmailVerification().then(() => setTimer(usr.user,5)) return await sendVerifyEmail.then(msg => { console.log('Finishing...',msg) if(msg.txt !== 'waiting') { if(msg.error) { throw msg.txt } else return msg.txt } }).catch(() => { throw 'EMAIL_NOT_SENT' }) }).catch(() => { throw 'USER_NOT_CREATED' }) } catch (err) { throw 'USER_ALREADY_REGISTERED' } } } 。我们先解决这个问题 -

children

现在我们可以编写您的 const node = (id,...children) => ({ constructor: node,id,children }) const tree = node(1,node(2,node(3,node(7),node(6)),node(4),node(5))) -

traverse
function* traverse(t)
{ switch (t?.constructor)
  { case node:
      yield t.id
      for (const c of t.children)
      { yield *traverse(c)
        yield t.id
      }
  }
}
for (const v of traverse(tree))
  console.log(v)

或者我们可以将它们全部收集在一个字符串中

1
2
3
7
3
6
3
2
4
2
5
2
1

展开下面的代码片段以在您自己的浏览器中验证结果 -

console.log(Array.from(traverse(tree)).join(""))

const node = (id,children })

function* traverse(t)
{ switch (t?.constructor)
  { case node:
      yield t.id
      for (const c of t.children)
      { yield *traverse(c)
        yield t.id
      }
  }
}

const tree =
  node(1,node(5)))

console.log(Array.from(traverse(tree)).join(""))
,

您可以从 children 数组中取出可见节点并获取未可见键的节点。

const
    getSequence = (key,seen = {}) => {
        seen[key] = true;

        const unseen = sequenceObj[key]
                .children
                .filter(k => !seen[k]);

        return unseen.length
            ? `${key}${unseen.flatMap(k => getSequence(k,seen)).join(key)}${key}`
            : key;
    },sequenceObj = { 1: { id: "Point_1cec2262-20f8-4985-adcb-b6d95a618d22",children: ["2"] },2: { id: "Point_02bdae16-1cdb-48e1-a601-7b1e526eedb8",children: ["1","3","4","5"] },3: { id: "Point_55a68ac0-17ef-48a2-bf9f-c70004a27d99",children: ["2","6","7"] },4: { id: "Point_8760427c-98bb-4e3e-85dd-59cba3b31c6f",5: { id: "Point_79a7bcec-d110-43dc-b9ac-1552538bc1a5",6: { id: "Point_37550cf0-4bd5-48b2-b32f-9018bd55c05f",children: ["3"] },7: { id: "Point_2de67998-9e1f-4b06-af18-77d558d68254",children: ["3"] } };

console.log(getSequence('1'));

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。