声明:下面的代码只是一个最基础的实现,没有经过严格的测试。
/**
* 二叉排序树(BST)
* 定义:对于任何一个非叶子节点,要求左子节点的值比父节点小,右子节点的值比父节点值大。如果有相同的值,可以在
* 左节点或者右节点
*/
public class BinarySortTree {
public Node root;
public static void main(String[] args) {
BinarySortTree tree = new BinarySortTree();
int[] arr={4,7,2,1,5,5,0};
for (int i : arr) {
tree.addNode(i);
}
tree.deleteNode(5);
tree.infixOrder();
//System.out.println(tree.searchParent(7));
}
public void addNode(int value){
if(root == null){
root = new Node(value);
}else {
addNode(root,value);
}
}
public Node search(int value){
return search(root,value);
}
public Node searchParent(int value){
if(root == null){
return null;
}
if(root.value == value){
return null;
}
return searchParent(root,value);
}
/**
* 删除节点,分三种情况:1,待删除节点是叶子节点。2,待删除节点只有一棵子树。3,待删除节点既有左子节点又有右子节点
* @param value 待删除的节点
*/
public void deleteNode(int value){
if(root == null){
return;
}
Node parent = searchParent(value);
Node node = search(value);
//第一种情况:待删除的节点是叶子节点
if(node.left == null && node.right == null){
if(parent.left != null && parent.left.value == value){
parent.left = null;
}
if(parent.right != null && parent.right.value == value){
parent.right = null;
}
node = null;
return;
}
// 第二种情况:待删除的节点只有一棵子树(左子树或右子树的情况)
if(node.left !=null && node.right == null){
if(parent.left.value == value){
parent.left=node.left;
}else if(parent.right.value == value){
parent.right=node.left;
}
node = null;
return;
}else if(node.right !=null && node.left == null){
if(parent.left.value == value){
parent.left=node.right;
}else if(parent.right.value == value){
parent.right=node.right;
}
node = null;
return;
}
//第二种情况:待删除的节点既有左子树又有右子树的情况)
/**
* 两种处理方式:寻找待删除节点右子树中的最小节点或者左子树的最大节点,将该节点的值赋给待删除节点并删除该节点即可
* 中序遍历中:右子树的最小节点即该节点的后继节点。左子树的最大节点即该节点的前驱节点。
* 有后继节点或者前驱节点代替该节点,然后删除后继结点或者前驱节点
*/
if(node.left != null && node.right != null){
int v = delRightTreeMin(node);
node.value=v;
}
}
//以node节点作为根节点,寻找右子树的最小值节点。删除该节点并返回该节点的值
//也可以寻找左子树的最大节点,一样的
private int delRightTreeMin(Node node){
Node tempNode=node.right;
while (tempNode.left != null){
tempNode=tempNode.left;
}
int value = tempNode.value;
deleteNode(value);
return value;
}
// 对于二叉排序树,中序遍历时输出的值 是 升序排列的
public void infixOrder(){
if(root != null){
infixOrder(root);
}else{
System.out.println("该二叉树为空");
}
}
//递归查找父节点
private Node searchParent(Node curNode,int value){
if(curNode.left != null ){
if(curNode.left.value == value){
return curNode;
}else{
Node node = searchParent(curNode.left,value);
if(node != null){
return node;
}
}
}
if(curNode.right != null ){
if(curNode.right.value == value){
return curNode;
}else{
Node node = searchParent(curNode.right,value);
if(node != null){
return node;
}
}
}
return null;
}
//使用递归的方式查找node
private Node search(Node curNode,int value){
if(curNode.value == value){
return curNode;
}
if(curNode.left != null){
Node node=search(curNode.left,value);
if(node != null){
return node;
}
}
if(curNode.right != null){
Node node=search(curNode.right,value);
if(node != null){
return node;
}
}
return null;
}
//中序遍历,先左节点再父节点,后右节点
private void infixOrder(Node node){
if(node==null){
return;
}
//每次都是先输出父节点
if(node.left!=null){
infixOrder(node.left);
}
System.out.println(node);
if(node.right!=null){
infixOrder(node.right);
}
}
/**
* 使用递归的方式新增元素:按照二叉排序树的定义,如果待插入的值比父节点小,则作为左节点。反之则为右节点。
* 值插入的逻辑:先从根节点开始,插入的值和根节点的值比较大小,放到合适的位置。如果根节点有左节点或右节点,那么根节点
* 的左节点或者有节点作为新的父节点,继续和待插入的值比较。直至父节点为null。
* @param parentNode 待插入节点的父节点
* @param value 待插入的值
*/
private void addNode(Node parentNode,int value){
if(parentNode == null){
return;
}
if(value < parentNode.value ){
if(parentNode.left == null){
parentNode.left=new Node(value);
}else{
//如果父节点存在左节点,那么该左节点作为新的父节点进行递归
addNode(parentNode.left,value);
}
}
if(value >= parentNode.value){
if(parentNode.right == null){
parentNode.right=new Node(value);
}else{
//如果父节点存在右节点,那么该右节点作为新的父节点进行递归
addNode(parentNode.right,value);
}
}
}
class Node{
//value
private Integer value;
//左节点
public Node left;
//右节点
public Node right;
public Node(Integer value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
}
}