已编写部分BinarySearchTree代码,求指导完成第二个实现文件
如何完成二叉搜索树(BinarySearchTree)的第二个实现文件?
嘿,我来帮你梳理下怎么搞定这个二叉搜索树的第二个实现文件~先看看你已经写的代码片段:
package u7a3; /** * generic binary search-tree with integer keys. * Empty trees are encoded as null references. * * @param <T> The type of the things which are managed in the binary * search tree */ public class BinarySearchTree<T> { /** * The key by which the thing is refered to. Must be unique. */ public int key; /** * The thing which is managed in the binary search tree. */ // 这里你应该是要加一个泛型属性,比如 public T value; }
首先得明确:你说的「第二个实现文件」,大概率是把二叉树的核心操作(插入、查找、删除、遍历等)和节点定义分开,让职责更清晰——第一个文件只做节点的结构定义,第二个文件专门实现操作逻辑。下面分步骤给你讲:
第一步:补全第一个文件的节点定义
先把第一个文件的BinarySearchTree类补全,它只需要负责描述树的节点结构,尽量做好封装(把成员变量设为private,提供getter/setter,避免外部随便修改key破坏树的结构):
package u7a3; /** * generic binary search-tree with integer keys. * Empty trees are encoded as null references. * * @param <T> The type of the things which are managed in the binary * search tree */ public class BinarySearchTree<T> { private int key; private T value; private BinarySearchTree<T> left; // 左子树 private BinarySearchTree<T> right; // 右子树 // 构造方法:创建一个非空节点 public BinarySearchTree(int key, T value) { this.key = key; this.value = value; this.left = null; this.right = null; } // Getter和Setter,保证封装性 public int getKey() { return key; } public void setKey(int key) { this.key = key; } public T getValue() { return value; } public void setValue(T value) { this.value = value; } public BinarySearchTree<T> getLeft() { return left; } public void setLeft(BinarySearchTree<T> left) { this.left = left; } public BinarySearchTree<T> getRight() { return right; } public void setRight(BinarySearchTree<T> right) { this.right = right; } }
第二步:编写第二个文件的操作逻辑
新建一个比如叫BinarySearchTreeOperations的类,把二叉搜索树的所有核心操作都放在这里,用静态方法实现(因为操作是针对整个树的根节点,不需要实例化这个操作类):
package u7a3; public class BinarySearchTreeOperations { // 1. 插入节点:递归实现,支持更新重复key的value public static <T> BinarySearchTree<T> insert(BinarySearchTree<T> root, int key, T value) { // 空树直接返回新节点 if (root == null) { return new BinarySearchTree<>(key, value); } // 小于当前key,插入左子树 if (key < root.getKey()) { root.setLeft(insert(root.getLeft(), key, value)); } // 大于当前key,插入右子树 else if (key > root.getKey()) { root.setRight(insert(root.getRight(), key, value)); } // 等于当前key,更新value(也可以抛出异常提示重复) else { root.setValue(value); } return root; } // 2. 查找节点:根据key找对应的值 public static <T> T search(BinarySearchTree<T> root, int key) { // 空树或者找到目标节点,返回结果 if (root == null || root.getKey() == key) { return root != null ? root.getValue() : null; } // 小于当前key,往左找;否则往右找 return key < root.getKey() ? search(root.getLeft(), key) : search(root.getRight(), key); } // 3. 删除节点:最复杂的操作,分三种情况处理 public static <T> BinarySearchTree<T> delete(BinarySearchTree<T> root, int key) { if (root == null) { return null; } // 找到要删除的节点 if (key < root.getKey()) { root.setLeft(delete(root.getLeft(), key)); } else if (key > root.getKey()) { root.setRight(delete(root.getRight(), key)); } else { // 情况1:叶子节点(没有子节点),直接删除 if (root.getLeft() == null && root.getRight() == null) { return null; } // 情况2:只有一个子节点,返回这个子节点代替当前节点 else if (root.getLeft() == null) { return root.getRight(); } else if (root.getRight() == null) { return root.getLeft(); } // 情况3:有两个子节点,找右子树的最小节点(后继节点)代替当前节点 else { BinarySearchTree<T> minRightNode = findMinNode(root.getRight()); // 替换当前节点的key和value root.setKey(minRightNode.getKey()); root.setValue(minRightNode.getValue()); // 删除那个后继节点 root.setRight(delete(root.getRight(), minRightNode.getKey())); } } return root; } // 辅助方法:找树中的最小节点(最左节点) private static <T> BinarySearchTree<T> findMinNode(BinarySearchTree<T> node) { while (node.getLeft() != null) { node = node.getLeft(); } return node; } // 4. 中序遍历:升序输出所有节点的key和value public static <T> void inorderTraversal(BinarySearchTree<T> root) { if (root != null) { inorderTraversal(root.getLeft()); System.out.printf("Key: %d, Value: %s%n", root.getKey(), root.getValue()); inorderTraversal(root.getRight()); } } }
第三步:测试使用示例
你可以写个测试类验证功能,比如:
package u7a3; public class BstTest { public static void main(String[] args) { BinarySearchTree<String> root = null; // 插入节点 root = BinarySearchTreeOperations.insert(root, 5, "Apple"); root = BinarySearchTreeOperations.insert(root, 3, "Banana"); root = BinarySearchTreeOperations.insert(root, 7, "Cherry"); // 查找节点 System.out.println("查找key=3的值:" + BinarySearchTreeOperations.search(root, 3)); // 中序遍历 System.out.println("中序遍历结果:"); BinarySearchTreeOperations.inorderTraversal(root); // 删除节点 root = BinarySearchTreeOperations.delete(root, 5); System.out.println("删除key=5后的中序遍历:"); BinarySearchTreeOperations.inorderTraversal(root); } }
这样拆分的好处是职责单一:BinarySearchTree只负责节点的结构,BinarySearchTreeOperations负责所有业务操作,代码更清晰,也方便后续维护扩展。
内容的提问来源于stack exchange,提问作者Jo An
相关产品推荐
相关产品推荐

