Binary Sort Tree
Binary Search Tree
For any non-leaf node of a binary sorted tree, the value of the left child node is required to be smaller than that of the current node, and the value of the right child node is greater than that of the current node.
If the values are the same, you can place the node in a left or right child node
Creation and traversal of binary sort trees
Medium Order Traversal Binary Sort Tree
package tree.binarysearchtree; public class BinarySearchTreeDemo01 { public static void main(String[] args) { int[] arr = {7,3,10,12,5,1,9}; BinarySortTree binarySortTree = new BinarySortTree(); // cyclical addition for (int i = 0; i < arr.length; i++) { binarySortTree.add(new Node(arr[i])); } System.out.println("infix order "); binarySortTree.infixOrder(); } } // create binary search tree class BinarySortTree{ private Node root; // add public void add(Node node){ if(root==null){ root = node; } else{ root.add(node); } } // traversal public void infixOrder(){ if(root!=null){ root.infixOrder(); } else{ System.out.println("can not traverse"); } } } // create Node class Node{ int value; Node left; Node right; public Node(int value) { this.value = value; } @Override public String toString() { return "Node{" + "value=" + value + '}'; } // add Node recursively public void add(Node node ){ if(node == null){ return; } // determine the relationship of node's value and // the value of the root node of the current subtree if(node.value<this.value){ if(this.left==null){ this.left = node; }else{ // If the left subtree of the current node is not empty, add the node recursively to the left this.left.add(node); } } else{ // The value of the added node is greater than that of the current node if(this.right==null){ this.right = node; } else{ this.right.add(node); } } } // infix order traversal public void infixOrder(){ if(this.left!=null){ this.left.infixOrder(); } System.out.println(this.value); if(this.right!=null){ this.right.infixOrder(); } } }
Deletion of Binary Trees
-
Delete leaf nodes
- Find the node targetNode that needs to be deleted first
- Find the parent of the targetNode (if parent exists)
- Determine whether targetNode is a parent's left or right child node
- Delete according to previous situation
- Left Child NodeParent.left= null;
- Right Child NodeParent.right= null;
-
Delete nodes with only one subtree
-
Find the node targetNode that needs to be deleted first
-
Find the parent of the targetNode (if parent exists)
-
Determines whether the child node of targetNode is a left or right child node
-
Is targetNode a parent's left or right child node
-
If the child node of targetNode is a left child node
-
If targetNode is the left child node of parent
parent.left = targetNode.left
-
If targetNode is the right child node of parent
Parent.right = targetNode.left
-
-
If the child node of targetNode is a left child node
-
If targetNode is the left child node of parent
parent.left = targetNode.right
-
If targetNode is the right child node of parent
Parent.right = targetNode.right
-
-
-
Delete nodes with two subtrees
- The node targetNode to be deleted needs to be found first
- Find parent node of targetNode
- Find the smallest node (or the largest value of the left subtree) from the right subtree of targetNode
- Save the value of the smallest node with a temporary variable
- Delete the smallest node
- targetNode.value = temp
- Find Nodes to Delete
// class Node // find node wait for deleting /** * * @param value The value of node you wish to delete * @return if find it, return this node, or return null */ public Node search(int value){ if(value==this.value){ // find it return this; } else if(value<this.value){ // if value smaller than current node, find it recursively to left side // if left node is null, return null if(this.left==null){ return null; } return this.left.search(value); } else{ // recursively search to right side if(this.right==null){ return null; } return this.right.search(value); } }
- Find the parent of the node to be deleted
// class Node // find the parent node of the node to be deleted /** * * @param value the value of node you want to find * @return the parent node of the node to be deleted, if not found, return null */ 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 is smaller than current value and left node of current node is not null // recursively find left side if(value<this.value && this.left!=null){ this.left.searchParent(value); } else if(value >= this.value && this.right!=null){ this.right.searchParent(value); } else{ return null; } } }
- Encapsulate methods to find and parent nodes
// class BinarySortTree // find node to be deleted public Node search(int value){ if(root==null){ return null; } else{ return root.search(value); } } // find parent node public Node searchParent(int value){ if(root==null){ return null; } else{ return root.searchParent(value); } }
- Delete Node
- Is the root node empty
- Find the node to delete (determine if it is empty and if the tree has only one root node)
- Find the parent of the node to be deleted
- Delete leaf nodes
- Delete a node with a subtree
- Delete nodes with two subtrees
- Find the minimum value of the node's right subtree or the maximum value of the left subtree
- Find the minimum public int delRightTreeMin(Node node){} of the subtree with node as the root node Delete the minimum node and return the minimum value
// class BinarySortTree // 1. return the min value of BST with node as the root // 2. delete the smallest node of BST with node as the root /** * * @param node Incoming node ( as root node of BST) * @return the min value of BST with node as the root */ public int delRightTreeMin(Node node){ Node target = node; // cyclic search left node to find the minimum node while(target.left!=null){ target = target.left; } // now target is the minimum value delete(target.value); return target.value; }
// delete node public void delete(int value){ if (root==null){ return; } else{ // 1. find targetNode (node to be deleted) Node targetNode = search(value); if(targetNode==null){ return; } // if this tree only have one node if(root.left==null && root.right==null){ root = null; return; } // find parent node of targetNode Node parent = searchParent(value); // if node to be deleted is leaf node if(targetNode.left == null && targetNode.right == null){ // determine target node is right or left node of parent node if(parent.left!=null && parent.left.value == value){ parent.left = null; } else if(parent.right != null && parent.right.value == value){ parent.right = null; } } else if(targetNode.left != null && targetNode.right != null){ // delete node who has two subtrees // find the min value of right tree int min = delRightTreeMin(targetNode.right); targetNode.value = min; } else{ // delete node only with one subtree // if node to be deleted has left node if(targetNode.left!=null){ // if targetNode is left node of parent node if(parent.left.value == value){ parent.left = targetNode.left; } else{ // target node is right node of parent node parent.right = targetNode.left; } } else{ // node to be deleted has right node // if target node is left node of parent node if(parent.left.value == value){ parent.left = targetNode.right; } else{ parent.right = targetNode.right; } } } } }
test
public static void main(String[] args) { int[] arr = {7,3,10,12,5,1,9,2}; BinarySortTree binarySortTree = new BinarySortTree(); // cyclical addition for (int i = 0; i < arr.length; i++) { binarySortTree.add(new Node(arr[i])); } System.out.println("infix order "); binarySortTree.infixOrder(); System.out.println("\nafter deletion"); // test delete leaf node binarySortTree.delete(7); binarySortTree.infixOrder();
output
infix order 1 2 3 5 7 9 10 12 after deletion 1 2 3 5 9 10 12
Complete Code
package tree.binarysearchtree; import java.util.function.Predicate; public class BinarySearchTreeDemo01 { public static void main(String[] args) { int[] arr = {7,3,10,12,5,1,9,2}; BinarySortTree binarySortTree = new BinarySortTree(); // cyclical addition for (int i = 0; i < arr.length; i++) { binarySortTree.add(new Node(arr[i])); } System.out.println("infix order "); binarySortTree.infixOrder(); System.out.println("\nafter deletion"); // test delete leaf node binarySortTree.delete(7); binarySortTree.infixOrder(); } } // create binary search tree class BinarySortTree{ private Node root; // find node to be deleted public Node search(int value){ if(root==null){ return null; } else{ return root.search(value); } } // find parent node public Node searchParent(int value){ if(root==null){ return null; } else{ return root.searchParent(value); } } // 1. return the min value of BST with node as the root // 2. delete the smallest node of BST with node as the root /** * * @param node Incoming node ( as root node of BST) * @return the min value of BST with node as the root */ public int delRightTreeMin(Node node){ Node target = node; // cyclic search left node to find the minimum node while(target.left!=null){ target = target.left; } // now target is the minimum value delete(target.value); return target.value; } // delete node public void delete(int value){ if (root==null){ return; } else{ // 1. find targetNode (node to be deleted) Node targetNode = search(value); if(targetNode==null){ return; } // if this tree only have one node if(root.left==null && root.right==null){ root = null; return; } // find parent node of targetNode Node parent = searchParent(value); // if node to be deleted is leaf node if(targetNode.left == null && targetNode.right == null){ // determine target node is right or left node of parent node if(parent.left!=null && parent.left.value == value){ parent.left = null; } else if(parent.right != null && parent.right.value == value){ parent.right = null; } } else if(targetNode.left != null && targetNode.right != null){ // delete node who has two subtrees // find the min value of right tree int min = delRightTreeMin(targetNode.right); targetNode.value = min; } else{ // delete node only with one subtree // if node to be deleted has left node if(targetNode.left!=null){ // if targetNode is left node of parent node if(parent.left.value == value){ parent.left = targetNode.left; } else{ // target node is right node of parent node parent.right = targetNode.left; } } else{ // node to be deleted has right node // if target node is left node of parent node if(parent.left.value == value){ parent.left = targetNode.right; } else{ parent.right = targetNode.right; } } } } } // add public void add(Node node){ if(root==null){ root = node; } else{ root.add(node); } } // traversal public void infixOrder(){ if(root!=null){ root.infixOrder(); } else{ System.out.println("can not traverse"); } } } // create Node class Node{ int value; Node left; Node right; public Node(int value) { this.value = value; } // find node wait for deleting /** * * @param value The value of node you wish to delete * @return if find it, return this node, or return null */ public Node search(int value){ if(value==this.value){ // find it return this; } else if(value<this.value){ // if value smaller than current node, find it recursively to left side // if left node is null, return null if(this.left==null){ return null; } return this.left.search(value); } else{ // recursively search to right side if(this.right==null){ return null; } return this.right.search(value); } } // find the parent node of the node to be deleted /** * * @param value the value of node you want to find * @return the parent node of the node to be deleted, if not found, return null */ 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 is smaller than current value and left node of current node is not null // recursively find left side 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; } } } @Override public String toString() { return "Node{" + "value=" + value + '}'; } // add Node recursively public void add(Node node ){ if(node == null){ return; } // determine the relationship of node's value and // the value of the root node of the current subtree if(node.value<this.value){ if(this.left==null){ this.left = node; }else{ // If the left subtree of the current node is not empty, add the node recursively to the left this.left.add(node); } } else{ // The value of the added node is greater than that of the current node if(this.right==null){ this.right = node; } else{ this.right.add(node); } } } // infix order traversal public void infixOrder(){ if(this.left!=null){ this.left.infixOrder(); } System.out.print(this.value+" "); if(this.right!=null){ this.right.infixOrder(); } } }