package com.hblg.binarysorttree;
/**
* @author i
* @create 2019/10/20 9:35
* @Description 二叉排序树
* 二叉排序树特点 任何一个非叶子节点 要求左边节点的值比当前节点的值小 右边节点的值比当前节点的值大
*
*
*/
public class BinarySortTreeDemo {
public static void main(String[] args) {
int[] array = {7, 3, 10, 12, 5, 1, 9, 2};
BinarySortTree binarySortTree = new BinarySortTree();
for (int value : array) {
binarySortTree.add(new Node(value));
}
System.out.println("遍历");
binarySortTree.infixOrder();
binarySortTree.deleteNode(new Node(10));
System.out.println("删除后");
binarySortTree.infixOrder();
}
}
class BinarySortTree {
private Node rootNode;
//添加
public void add(Node node) {
if (node == null) {
throw new NullPointerException("data is null!");
} else if (rootNode == null) {
rootNode = node;//如果root节点为空 直接挂载
} else {
rootNode.addNode(node);
}
}
//中序遍历
public void infixOrder() {
if (rootNode == null) {
throw new NullPointerException("root node is null!");
} else {
rootNode.infixOrder();
}
}
/***
* 查找要删除的节点
* @param node
* @return
*/
public Node searchDeleteNode(Node node) {
if (node == null) {
return null;
}
return rootNode.searchDeleteNode(node);
}
/***
* 寻找要删除的叶子节点的父节点
* @param parentNode
* @return
*/
public Node searchDeleteParentNode(Node parentNode) {
if (parentNode == null) {
return null;
}
return rootNode.searchDeleteNodeParentNode(parentNode);
}
//找到该节点左边最小的数 删除
private int deleteRightMin(Node node) {
Node currentNode = node;
while (currentNode.leftNode != null) {
currentNode = currentNode.leftNode;
}
int value = currentNode.getValue();
deleteNode(currentNode);
return value;
}
/***
* 二叉排序树 删除
* 1.删除叶子节点
* 2.删除只有一颗子树的节点
* 3.删除有两颗子树的节点
*/
/***
* 1.删除叶子节点
* 1.先找到要删除的节点
* 2.找到眼删除节点的父节点 如果该节点是root节点 则直接删除
* 3.确定要删除的节点是parentNode的左子节点 还是右子节点
* 根据前面的情况来应对删除
* 左子节点 prentNode.left = null;
* 右子节点 parentNode.right = null;
*/
/***
* 2.删除只有一颗子树的节点
* 1.先找到要删除的节点
* 2.找到要删除节点的父节点 如果该父节点是root节点 则直接删除
* 3.确定targetNode是父节点的左子节点还是右子节点
* 4.如果targetNode是父节点的左子节点
* 4.1
*
*
*/
/***
* 3.删除的有两颗子树的节点
* 1.先找到要删除的节点
* 2.找到要删除节点的父节点,如果该节点是root节点 直接删除
* 3.从targetNode的右子树找到最小的节点。
* 4.用一个临时变量,将最小节点值保存在temp = 11;
* 5.删除该最小节点
* 6.targent.value= temp;
*/
/***
* 删除某一个节点
* @param node
*/
public void deleteNode(Node node) {
if (node == null) {//如果为null 直接返回
return;
} else {
//查找要删除的节点
Node currentNode = searchDeleteNode(node);
//如果没有找到 直接返回
if (currentNode == null) {
return;
}
//查找当前节点的父节点
Node parentNode = searchDeleteParentNode(node);
System.out.println("parentNode:" + parentNode);
//如果当前节点的父节点为根节点 root 直接删除
if (parentNode == null) {
currentNode = null;
return;
}
//如果查找的节点的左节点和右节点都为空 表示该节点为叶子节点
if (currentNode.leftNode == null && currentNode.rightNode == null) {//删除叶子节点
if (parentNode.leftNode != null && parentNode.leftNode.getValue() == currentNode.getValue()) {
parentNode.leftNode = null;
} else if (parentNode.rightNode != null && parentNode.rightNode.getValue() == currentNode.getValue()) {
parentNode.rightNode = null;
}
} else if (currentNode.rightNode != null && currentNode.leftNode != null) {//删除只有一颗子节点的节点
int value = deleteRightMin(currentNode.rightNode);
currentNode.setValue(value);
} else {//删除有两颗子节点的节点
//删除的节点有左子节点
if (currentNode.leftNode != null) {
//如果currentNode是父节点左子节点
if (parentNode.leftNode.getValue() == node.getValue()) {
parentNode.leftNode = currentNode.leftNode;
} else {
//如果currentNode是父节点右节点
parentNode.rightNode = currentNode.leftNode;
}
} else {//删除的节点有右子节点
if (currentNode.rightNode != null) {
//如果currentNode是父节点的左子节点
if (parentNode.leftNode.getValue() == node.getValue()) {
parentNode.leftNode = currentNode.rightNode;
} else {
//如果删除的节点有右子节点
parentNode.rightNode = currentNode.rightNode;
}
}
}
}
}
}
}
class Node {
private int value;//数据
Node leftNode;//左节点
Node rightNode;//右节点
public Node(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
//添加
public void addNode(Node node) {
if (node.value < this.value) {//挂载左边
if (this.leftNode == null) {//如果当前节点的左子树为空 直接挂载
this.leftNode = node;
} else {//否则递归 左子节点
this.leftNode.addNode(node);
}
} else {//添加的节点值大于等于当前节点
if (this.rightNode == null) {//当前节点的右子树为空 直接挂载
this.rightNode = node;
} else {//递归 右子节点
this.rightNode.addNode(node);
}
}
}
//中序遍历
public void infixOrder() {
if (this.leftNode != null) {
this.leftNode.infixOrder();//不为空 递归查找左子树
}
System.out.println(this);
if (this.rightNode != null) {
this.rightNode.infixOrder();//不为空 递归查找右子树
}
}
/***
* 查找要删除的节点
* @param node
* @return
*/
public Node searchDeleteNode(Node node) {
//第一种情况 直接找到
if (this.value == node.value) {
return node;
} else if (node.value < this.value) {
if (this.leftNode == null) {
return null;
}
return this.leftNode.searchDeleteNode(node);
} else {
if (this.rightNode == null) {
return null;
}
return this.rightNode.searchDeleteNode(node);
}
}
/***
* 查找删除节点的父节点
* @param node
* @return
*/
public Node searchDeleteNodeParentNode(Node node) {
//找到
if ((this.leftNode != null && this.leftNode.value == node.value) || this.rightNode != null && this.rightNode.value == node.value) {
return this;
} else {
if (this.leftNode != null && node.value < this.value) {
//如果要找的值小于当前节点的左子节点的值 向左递归查找
return this.leftNode.searchDeleteNodeParentNode(node);
} else if (this.rightNode != null && node.value >= this.value) {
//如果当前节点的值大于等于右子节点的值 向右递归查找
return this.rightNode.searchDeleteNodeParentNode(node);
} else {
return null;//表示没有找到
}
}
}
}