二叉排序树
Binary Search 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{ // 如果当前节点的左子树不为空,则向左递归添加node
this.left.add(node);
}
} else{ // 添加的节点的值大于当前节点的值
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();
}
}
}
二叉树的删除
-
删除叶子节点
- 先找到需要删除的节点 targetNode
- 找到 targetNode 的父节点 parent(是否存在父节点)
- 判断 targetNode 是 parent的左子节点还是右子节点
- 根据前面的情况进行删除
- 左子节点 parent.left = null;
- 右子节点 parent.right = null;
-
删除只有一颗子树的节点
-
先找到需要删除的节点 targetNode
-
找到 targetNode 的父节点 parent(是否存在父节点)
-
确定 targetNode 的子节点是左子节点还是右子节点
-
targetNode 是parent 的左子节点还是右子节点
-
如果targetNode 的子节点是左子节点
-
如果 targetNode 是parent 的左子节点
parent.left = targetNode.left
-
如果 targetNode 是parent 的右子节点
Parent.right = targetNode.left
-
-
如果targetNode 的子节点是左子节点
-
如果 targetNode 是parent 的左子节点
parent.left = targetNode.right
-
如果 targetNode 是parent 的右子节点
Parent.right = targetNode.right
-
-
-
删除有两颗子树的节点
- 需要先找到要删除的节点 targetNode
- 找到 targetNode 的父节点 parent
- 从 targetNode 的右子树找到最小的节点(或左子树最大的值)
- 用一个临时变量,保存最小节点的值
- 删除该最小节点
- targetNode.value = temp
- 找待删除的节点
// 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);
}
}
- 找待删除节点的父节点
// 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;
}
}
}
- 封装查找节点和父节点的方法
// 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);
}
}
- 删除节点
- 根节点是否为空
- 找到待删除节点(判断是否为空 以及 树是否只有根节点一个节点)
- 找待删除节点的父节点
- 删除叶子节点
- 删除有一颗子树的节点
- 删除有两颗子树的节点
- 找该节点右子树的最小值 或 左子树的最大值
- 找到以node为根节点的子树的最小值 public int delRightTreeMin(Node node){} 删除该最小值的节点并返回该最小值
// 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
完整代码
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{ // 如果当前节点的左子树不为空,则向左递归添加node
this.left.add(node);
}
} else{ // 添加的节点的值大于当前节点的值
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();
}
}
}