二进制搜索树(BST)–搜索插入和删除
时间:2020-02-23 14:41:15 来源:igfitidea点击:
在本教程中,我们将讨论二进制搜索树数据结构。
我们将实现在Binary Search Tree中搜索,插入和删除值的功能。
我们将以递归方式和迭代方式实施这些操作。
二进制搜索树
二叉搜索树具有以下属性:
所有节点的左子节点应始终小于父节点。
正确的子节点始终大于父节点。
在以下各节中,我们将介绍如何以递归和迭代方式在BST中搜索,插入和删除。
让我们首先创建我们的二叉树数据结构:
public class BinaryTree { public TreeNode root; public static class TreeNode { public TreeNode left; public TreeNode right; public Object data; public TreeNode(Object data) { this.data = data; left = right = null; } } }
注意,上述实现不是二叉搜索树,因为在树中插入元素没有限制。
BST递归搜索
以下Java程序包含用于在BST中递归搜索值的函数。
public class SearchInsertRemoveFromTree { public static void main(String[] args) { /** * Our Example Binary Search Tree * 10 * 5 20 * 4 8 15 25 */ BinaryTree tree = new BinaryTree(); tree.root = new TreeNode(10); tree.root.left = new TreeNode(5); tree.root.right = new TreeNode(20); tree.root.left.left = new TreeNode(4); tree.root.left.right = new TreeNode(8); tree.root.right.left = new TreeNode(15); tree.root.right.right = new TreeNode(25); System.out.println("Search Value 2 is in tree? " + searchRecursively(tree.root, 2)); System.out.println("Search Value 10 in tree? " + searchRecursively(tree.root, 10)); } public static boolean searchRecursively(TreeNode root, int value) { if (root == null) return false; if ((int) root.data == value) return true; if (value < (int) root.data) return searchRecursively(root.left, value); else if (value > (int) root.data) return searchRecursively(root.right, value); return false; } }
BST反复搜索
要迭代搜索,请改用以下方法:
public static boolean searchIteratively(TreeNode root, int value) { while (root != null) { if ((int) root.data == value) return true; if (value < (int) root.data) root = root.left; else root = root.right; } return false; }
让我们看一下如何在二进制搜索树中插入新节点。
BST递归插入
public static TreeNode insertionRecursive(TreeNode root, int value) { if (root == null) return new TreeNode(value); if (value < (int) root.data) { root.left = insertionRecursive(root.left, value); } else if (value > (int) root.data) { root.right = insertionRecursive(root.right, value); } return root; } public static void printInorderTraversal(TreeNode root) { if (root != null) { printInorderTraversal(root.left); System.out.print(root.data + " "); printInorderTraversal(root.right); } }
在main方法中调用上述方法:
tree.root = insertionRecursive(tree.root, 24); tree.root = insertionRecursive(tree.root, 2); printInorderTraversal(tree.root);
该树以有序遍历的形式打印。
BST插入迭代
要将节点迭代地插入BST树中,我们将需要使用两个指针遍历该树。
public static TreeNode insertionIterative(TreeNode root, int value) { TreeNode current, parent; TreeNode tempNode = new TreeNode(value); if (root == null) { root = tempNode; return root; } else { current = root; } while (true) { parent = current; if (value < (int) current.data) { current = current.left; if (current == null) { parent.left = tempNode; return root; } } else if (value > (int) current.data) { current = current.right; if (current == null) { parent.right = tempNode; return root; } } } }
BST递归删除元素
从BST中删除元素比搜索和插入要复杂一些,因为我们必须确保BST属性得到保留。
要删除节点,我们需要先搜索它。
然后,我们需要确定该节点是否有子节点。
如果没有孩子-删除即可。
如果是单个孩子-将那个孩子复制到该节点。
如果有两个孩子-确定右子树中的下一个最高元素(顺序后继)。
用顺序后继节点替换要删除的节点。
删除顺序的后继副本。
可通过在节点的右子节点中找到最小值来获得有序后继者。
以下Java程序从BST中删除元素:
public static TreeNode deleteRecursively(TreeNode root, int value) { if (root == null) return root; if (value < (int) root.data) { root.left = deleteRecursively(root.left, value); } else if (value > (int) root.data) { root.right = deleteRecursively(root.right, value); } else { if (root.left == null) { return root.right; } else if (root.right == null) return root.left; root.data = inOrderSuccessor(root.right); root.right = deleteRecursively(root.right, (int) root.data); } return root; } public static int inOrderSuccessor(TreeNode root) { int minimum = (int) root.data; while (root.left != null) { minimum = (int) root.left.data; root = root.left; } return minimum; }
在main
方法中调用上述delete方法:
tree.root = deleteRecursively(tree.root, 4); tree.root = deleteRecursively(tree.root, 20); printInorderTraversal(tree.root);
输出为:2 5 8 10 15 24 25
让我们反复进行相同的操作。
BST迭代删除元素
public static TreeNode deleteNodeIteratively(TreeNode root, int value) { TreeNode parent = null, current = root; boolean hasLeft = false; if (root == null) return root; while (current != null) { if ((int) current.data == value) { break; } parent = current; if (value < (int) current.data) { hasLeft = true; current = current.left; } else { hasLeft = false; current = current.right; } } if (parent == null) { return deleteNodeIteratively(current); } if (hasLeft) { parent.left = deleteNodeIteratively(current); } else { parent.right = deleteNodeIteratively(current); } return root; } private static TreeNode deleteNodeIteratively(TreeNode node) { if (node != null) { if (node.left == null && node.right == null) { return null; } if (node.left != null && node.right != null) { TreeNode inOrderSuccessor = deleteInOrderSuccessorDuplicate(node); node.data = inOrderSuccessor.data; } else if (node.left != null) { node = node.left; } else { node = node.right; } } return node; } private static TreeNode deleteInOrderSuccessorDuplicate(TreeNode node) { TreeNode parent = node; node = node.right; boolean rightChild = node.left == null; while (node.left != null) { parent = node; node = node.left; } if (rightChild) { parent.right = node.right; } else { parent.left = node.right; } node.right = null; return node; }
BST操作的时间复杂度为O(h)。
h是树的高度。