[064] Java “二叉排序树”

it2023-05-03  69

1、二叉排序树

概念:二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),其查找效率比链表要高。性质:二叉排序树的任何一个非叶子节点,左节点值 ≤ 当前节点值 ≤ 右节点值;所以经过中序遍历后其节点数值可有序排列。数组转二叉排序树: ​​​​​​​取出数组第一个元素作为二叉树的根节点;依次取出数组的其他元素,从根节点开始比较,比根节点小,就放在根节点的左子树,否则放在右子树;依次递归地往下比较,最终找到元素所在的位置;例如:数组 arr = {7, 3, 10, 12, 5, 1, 9, 2} 转为二叉排序树为:

2、Java代码 -- 实现二叉排序树的创建、中序遍历以及删除

// 二叉排序树 package DataStructures.BinarySortTree; /** * @author yhx * @date 2020/10/21 */ public class BinarySortTreeDemo { public static void main(String[] args) { int[] arr = {7, 3, 10, 12, 5, 1, 9, 2}; BinarySortTree binarySortTree = new BinarySortTree(); // 循环地添加节点到二叉排序树 for (int i : arr) { binarySortTree.add(new Node(i)); } System.out.println("中序遍历二叉排序树:"); binarySortTree.midOrder(); System.out.println(); binarySortTree.delNode(2); System.out.println("删除节点2后,中序遍历:"); binarySortTree.midOrder(); } } /** * 创建二叉排序树 */ class BinarySortTree { private Node root; /** * 添加节点的方法 * * @param node 待添加节点 */ public void add(Node node) { if (root == null) { root = node; } else { root.add(node); } } /** * 删除节点--查找要删除的节点 * * @param value 要查找节点的值 * @return 返回要删除的节点 */ public Node search(int value) { if (root == null) { return null; } else { return root.search(value); } } /** * 删除节点--查找要删除节点的父节点 * * @param value 要查找节点的值 * @return 返回要删除的节点的父节点 */ public Node searchParent(int value) { if (root == null) { return null; } else { return root.searchParent(value); } } /** * 删除节点--找到值最小的节点,并将其删除 * * @param node 二叉排序树的根节点 * @return 以node为根节点的二叉排序树,返回其最小值的节点 */ public int delRightTreeMin(Node node) { Node target = node; // 循环查找左节点,找到最小值 while (target.left != null) { target = target.left; } // 删除最小值的节点 delNode(target.value); return target.value; } /** * 删除节点--汇总 * * @param value 要删除节点的值 */ public void delNode(int value) { if (root == null) { return; } else { // 查找要删除的节点和删除节点的父节点 Node targetNode = search(value); Node parent = searchParent(value); // 1、如果没找到 if (targetNode == null) { return; } // 2、当前二叉排序树只有本身这个节点 if (root.left == null & root.right == null) { // 置空返回 root = null; return; } // 3、如果要删除的节点是叶子结点 if (targetNode.left == null && targetNode.right == null) { // 判断删除节点是左节点还是右节点,对应从父节点执行删除操作(置空) // 左 if (parent.left != null && parent.left.value == value) { parent.left = null; } // 右 else if (parent.right != null && parent.right.value == value) { parent.right = null; } } // 4、如果要删除的节点有两棵子树 else if (targetNode.left != null && targetNode.right != null) { // 从右子树找到最小值的节点,替换当前待删除节点 // 也可从左子树找到最大值的节点来替换 int minVal = delRightTreeMin(targetNode.right); targetNode.value = minVal; } // 5、删除的节点只有一棵子树 else { // 子树是左子节点 if (targetNode.left != null) { if (parent != null) { if (parent.left.value == value) { parent.left = targetNode.left; } else { parent.right = targetNode.left; } } else { root = targetNode.left; } } // 子树是右子节点 else { if (parent != null) { if (parent.left.value == value) { parent.left = targetNode.right; } else { parent.right = targetNode.right; } } else { root = targetNode.right; } } } } } /** * 中序遍历 */ public void midOrder() { if (root != null) { root.midOrder(); } else { System.out.println("二叉树为空,不能遍历"); } } } /** * 节点Node类 */ class Node { int value; Node left; Node right; /** * 构造器 * * @param value 节点的值 */ public Node(int value) { this.value = value; } /** * 添加节点,传入的节点值小于当前节点值,放在左子树,否则放在右子树 * * @param node 待添加的节点 */ public void add(Node node) { if (node == null) { return; } // 传入的节点值小于当前节点值,放在左子树,否则放在右子树 if (node.value < this.value) { // 如果左子节点为空,就挂在左子节点上 if (this.left == null) { this.left = node; } // 如果左子节点不为空,就递归添加 else { this.left.add(node); } } else { if (this.right == null) { this.right = node; } else { this.right.add(node); } } } /** * 删除节点--查找要删除的节点 * * @param value 希望删除的节点的值 * @return 返回节点,否则返回null */ public Node search(int value) { if (value == this.value) { return this; } // 值小于当前节点值,向左子树查找 else if (value < this.value) { if (this.left == null) { return null; } return this.left.search(value); } // 向右子树查找 else { if (this.right == null) { return null; } return this.right.search(value); } } /** * 删除节点--查找要删除节点的父节点 * * @param value 要查找的值 * @return 返回查找节点的父节点 */ public Node searchParent(int value) { if ((this.left != null && this.left.value == value) || (this.right != null && this.right.value == value)) { return this; } else { // 左子树查找 if (value < this.value && this.left != null) { return this.left.searchParent(value); } // 右子树查找 else if (value >= this.value && this.right != null) { return this.right.searchParent(value); } // 没有找到父节点 else { return null; } } } /** * 中序遍历 */ public void midOrder() { if (this.left != null) { this.left.midOrder(); } System.out.println(this); if (this.right != null) { this.right.midOrder(); } } @Override public String toString() { return "Node [ Value" + value + " ]"; } }

3、运行结果

中序遍历二叉排序树: Node [ Value1 ] Node [ Value2 ] Node [ Value3 ] Node [ Value5 ] Node [ Value7 ] Node [ Value9 ] Node [ Value10 ] Node [ Value12 ] 删除节点2后,中序遍历: Node [ Value1 ] Node [ Value3 ] Node [ Value5 ] Node [ Value7 ] Node [ Value9 ] Node [ Value10 ] Node [ Value12 ]

 

最新回复(0)