树结构插入节点后始终仅保留根节点的问题排查求助
问题排查与修复方案
我帮你梳理了代码里的两个关键问题,咱们一步步拆解解决:
一、为啥console.log(true)从来没输出?
看你这段代码:
if (!this.root) return this.currentTail = this.current = this.root = new Node(data, this.nodes++, 0); console.log(true);
当树还没有根节点的时候(第一次插入),这条return语句直接让函数结束了——后面的console.log(true)根本没机会运行!而当根节点存在时,虽然会跳过这个if,但你说第一次插入后也没看到日志,就是因为第一次插入时函数直接return了。
二、为啥新节点加不进去,反而只更新根节点?
你的插入逻辑有几个明显的bug:
- 递归时乱改实例的
currentTail:递归调用insertNode的时候,你修改的是整个树实例的currentTail属性,这会导致递归过程中这个变量被共享,逻辑彻底混乱。 - ID计数重复:第一次创建根节点时已经
this.nodes++了,后面在else分支又this.nodes++,会导致节点ID重复。 - 递归逻辑不对:你递归调用时没有处理插入的终止条件,反而一直修改全局的
currentTail,最后根本没创建新节点,反而可能覆盖了原来的节点。
修复后的完整代码
const Node = class graphNode { // 先修正你笔误的类名grahpNode constructor(data, id, family) { this.data = data; this.right = null; this.left = null; this.parent = null; // 用于返回上一页 this.id = id; // 页面唯一标识 this.family = family; // 标记页面所属分组 } } const Tree = class TreeClass { constructor() { this.root = null; this.current = this.root; // 跟踪当前所在节点 this.currentTail = this.current; // 跟踪插入位置的尾部节点 this.direction = true; // 插入方向:true左,false右 this.nodes = 0; // 节点计数(用于生成唯一ID) } // 插入节点方法 insertNode(data, direction = this.direction) { const leftRight = direction ? "left" : "right"; // 第一次插入:初始化根节点 if (!this.root) { this.root = new Node(data, this.nodes, 0); this.current = this.root; this.currentTail = this.root; this.nodes++; console.log(true); // 现在第一次插入会打印这条日志 return; } console.log(true); // 非第一次插入也会执行这条日志 // 用局部变量遍历找插入位置,不修改全局的currentTail(避免递归冲突) let tempTail = this.currentTail; while (tempTail[leftRight]) { tempTail = tempTail[leftRight]; } // 创建新节点并挂载 const newNode = new Node(data, this.nodes, this.current.id); newNode.parent = tempTail; tempTail[leftRight] = newNode; this.nodes++; // 更新全局的currentTail到新插入的节点(符合你原本的设计意图) this.currentTail = newNode; } }
修复点说明
- 修复日志不输出的问题:把原来的
return语句拆成单独的赋值和return,这样第一次插入时会先完成根节点初始化,执行日志后再结束函数;非第一次插入也会正常打印日志。 - 把递归改成循环查找:用局部变量
tempTail遍历找空的插入位置,避免递归修改全局属性导致的逻辑混乱,代码更清晰可靠。 - 修正ID计数逻辑:创建节点时先使用当前的
this.nodes作为ID,再自增,保证每个节点ID唯一且连续。 - 修正类名拼写:把
grahpNode改成正确的graphNode,避免潜在的命名问题。 - 明确
currentTail的更新逻辑:插入新节点后把currentTail更新为新节点,这样下次插入会从这个节点继续往指定方向添加,符合你原本的设计思路。
测试一下
你可以用这段代码验证:
const tree = new Tree(); tree.insertNode("首页"); // 第一次插入,打印true,ID为0 tree.insertNode("左侧子页面1"); // 打印true,插入到首页左侧,ID为1 tree.insertNode("左侧子页面2"); // 打印true,插入到左侧子页面1的左侧,ID为2 tree.direction = false; // 切换到右侧插入 tree.insertNode("右侧子页面1"); // 打印true,插入到左侧子页面2的右侧,ID为3 console.log(tree.root.left.left.right.data); // 输出 "右侧子页面1"
现在节点能正常添加,日志也会每次都打印,不会再出现覆盖根节点的问题了。
内容的提问来源于stack exchange,提问作者Mohammed El Ouali
相关产品推荐
相关产品推荐

