C#如何实现列表节点与树节点同步及满层初始化二叉树?
完全二叉树初始化、BFS查找及节点引用同步问题解决
一、现有代码的问题分析
- Tree类的Add方法逻辑错误:遍历列表时添加的是传入
node的左右子节点,而非当前遍历到的list[i]的子节点;当找到null位置时,直接给列表元素赋值新节点,但未将该节点关联到原树的父节点的左/右子节点,导致新节点不属于原树结构,列表与原树脱节。 - 对引用类型的理解偏差:Node是引用类型,列表中存储的是节点的引用,修改引用指向的对象的属性(如Data)会同步到原树,但如果直接给列表元素重新赋值(如
list[i] = new Node(...)),会改变列表中的引用指向,此时列表中的新节点和原树无关。
二、修正完全二叉树的按层填充逻辑
重新实现Add方法,用BFS遍历原树,找到第一个缺少左或右子节点的位置,将新节点添加为对应子节点,确保新节点纳入原树结构:
public class Node<T> { public T Data { get; set; } public Node(T data) { Data = data; } public Node<T> Parent { get; set; } public Node<T> Left { get; set; } public Node<T> Right { get; set; } } public class Tree<T> { public Node<T> root; public void CreateRoot(T data) { root = new Node<T>(data); } // 按层填充完全二叉树,添加新节点到第一个空缺的位置 public void Add(T data) { if (root == null) { CreateRoot(data); return; } // BFS队列,遍历所有节点找第一个缺少左/右子节点的父节点 Queue<Node<T>> queue = new Queue<Node<T>>(); queue.Enqueue(root); while (queue.Count > 0) { Node<T> current = queue.Dequeue(); // 完全二叉树优先填充左子树 if (current.Left == null) { current.Left = new Node<T>(data); current.Left.Parent = current; break; } else { queue.Enqueue(current.Left); } // 左子节点存在,检查右子节点 if (current.Right == null) { current.Right = new Node<T>(data); current.Right.Parent = current; break; } else { queue.Enqueue(current.Right); } } } }
三、BFS查找最左上的目标节点
以下实现查找匹配特定Data的最左上节点(即每层从左到右第一个符合条件的节点):
public class Tree<T> { // ... 保留上面的CreateRoot和Add方法 ... // BFS查找匹配目标Data的最左上节点 public Node<T> FindLeftmostTarget(T targetData) { if (root == null) return null; Queue<Node<T>> queue = new Queue<Node<T>>(); queue.Enqueue(root); while (queue.Count > 0) { int levelSize = queue.Count; // 遍历当前层的所有节点,从左到右检查 for (int i = 0; i < levelSize; i++) { Node<T> current = queue.Dequeue(); if (current.Data.Equals(targetData)) { return current; // 找到当前层最左侧的匹配节点,直接返回 } if (current.Left != null) queue.Enqueue(current.Left); if (current.Right != null) queue.Enqueue(current.Right); } } return null; // 未找到目标节点 } }
四、实现列表节点与原树同步的关键
因为Node是引用类型,只要列表中存储的是原树中节点的引用,修改节点的属性就会同步到原树:
正确同步方式
// 示例:通过BFS收集原树所有节点到列表 List<Node<int>> nodeList = new List<Node<int>>(); Queue<Node<int>> queue = new Queue<Node<int>>(); queue.Enqueue(tree.root); while (queue.Count > 0) { Node<int> current = queue.Dequeue(); nodeList.Add(current); if (current.Left != null) queue.Enqueue(current.Left); if (current.Right != null) queue.Enqueue(current.Right); } // 修改列表中节点的Data属性,原树对应节点的Data会同步改变 nodeList[2].Data = 99; // 此时原树中对应位置的节点Data也会变为99
错误方式(导致不同步)
// 错误:直接给列表元素赋值新节点,此时列表中的引用和原树无关 nodeList[2] = new Node<int>(100); // 原树中的对应节点不会有任何变化
五、完整演示示例
class Program { static void Main(string[] args) { Tree<int> tree = new Tree<int>(); // 初始化完全二叉树:按层填充1,2,3,4,5,6,7 tree.CreateRoot(1); tree.Add(2); tree.Add(3); tree.Add(4); tree.Add(5); tree.Add(6); tree.Add(7); // BFS查找目标节点(比如查找值为3的节点) Node<int> target = tree.FindLeftmostTarget(3); if (target != null) { Console.WriteLine($"找到目标节点:{target.Data}"); } // 收集原树所有节点到列表 List<Node<int>> nodeList = new List<Node<int>>(); Queue<Node<int>> queue = new Queue<Node<int>>(); queue.Enqueue(tree.root); while (queue.Count > 0) { Node<int> curr = queue.Dequeue(); nodeList.Add(curr); if (curr.Left != null) queue.Enqueue(curr.Left); if (curr.Right != null) queue.Enqueue(curr.Right); } // 修改列表中节点的Data,原树同步变化 nodeList[3].Data = 99; // 对应原树的4号节点 Console.WriteLine($"原树中4号节点的新值:{tree.root.Left.Left.Data}"); // 输出99 } }
内容的提问来源于stack exchange,提问作者W3BD3V3L0P3R
相关产品推荐
相关产品推荐

