参考文章
1 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2) 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3) 左、右子树也分别为二叉排序树;
4) 没有键值相等的结点。
代码实现如下,参考文章的图解和思路都超赞
/**
* 二叉排序树节点
*/
public class BSTreeNode {
/**
* 树的标识
*/
private int key;
/**
* 左子节点
*/
private BSTreeNode leftNode;
/**
* 右子节点
*/
private BSTreeNode rightNode;
public BSTreeNode() {
}
public BSTreeNode(int key) {
this.key = key;
}
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public BSTreeNode getLeftNode() {
return leftNode;
}
public void setLeftNode(BSTreeNode leftNode) {
this.leftNode = leftNode;
}
public BSTreeNode getRightNode() {
return rightNode;
}
public void setRightNode(BSTreeNode rightNode) {
this.rightNode = rightNode;
}
@Override
public String toString() {
return "BSTreeNode{" +
"key=" + key +
'}';
}
/**
* 添加子节点
*
* @param node
*/
public void add(BSTreeNode node) {
if (node == null) {
return;
}
if (this.key == node.key) {
System.out.println("该节点已存在");
return;
}
//放在该节点的左边
if (node.key < this.key) {
//如果没有左子节点,那么就放左子节点
if (this.leftNode == null) {
this.leftNode = node;
} else {
//继续递归
this.leftNode.add(node);
}
} else {
//放在该节点的右边
//如果没有右子节点,那么就放右子节点
if (this.rightNode == null) {
this.rightNode = node;
} else {
//继续递归
this.rightNode.add(node);
}
}
}
}
/**
* 二叉排序树(二叉搜索树 BinarySearchTree)
*
* 实现功能
* 1.添加
* 2.查找
* 3.删除
*/
public class BSTree {
/**
* 根节点
*/
private BSTreeNode root;
/**
* 添加节点
*
* @param node
*/
public void add(BSTreeNode node) {
if (root == null) {
root = node;
return;
}
//添加
root.add(node);
}
/**
* 删除节点
*
* @param key
*/
public void delete(int key) {
BSTreeNode parent = searchParent(key);
if (parent == null) {
System.out.println("parent未找到");
return;
}
//找到等待删除的节点
BSTreeNode target;
//跟parent的子节点进行比对
if (parent.getLeftNode() != null && parent.getLeftNode().getKey() == key) {
target = parent.getLeftNode();
} else {
target = parent.getRightNode();
}
System.out.println("key=" + key + "parent=" + parent + "target=" + target);
//那么就有三种情况
//1.待删除节点是叶子节点,那么就直接删
//2.待删除节点下有单个子节点,那么就节点上移
//3.待删除节点下存在两个子节点,那么就把右子节点下最小的值上移
int num = getChildNum(target);
//分别出来三种情况
if (num == 0) {
//进入情况1
//如果是左节点就删除左节点,是右节点就删除右节点
if (target == parent.getLeftNode()) {
parent.setLeftNode(null);
} else {
parent.setRightNode(null);
}
} else if (num == 1) {
//情况2
//如果是左节点就删除左节点的子节点上提,是右节点就上提右子节点的子节点
BSTreeNode child = getSingleChild(target);
if (target == parent.getLeftNode()) {
parent.setLeftNode(child);
} else {
parent.setRightNode(child);
}
} else {
//情况3 ,待删除的子节有两个子节点
//找出右子节点下最小的那个节点,替换到待删除节点
BSTreeNode minChild = getMinChild(target);
//删除该节点
delete(minChild.getKey());
//然后替换,完成
target.setKey(minChild.getKey());
}
}
/**
* 遍历查询子数下最小的节点
*
* @param target
* @return
*/
private BSTreeNode getMinChild(BSTreeNode target) {
BSTreeNode temp = target.getLeftNode();
while (temp.getLeftNode() != null) {
temp = temp.getLeftNode();
}
return temp;
}
/**
* 获取唯一的孩子节点
*
* @param target
* @return
*/
private BSTreeNode getSingleChild(BSTreeNode target) {
//左子节点存在就返回,否则返回右子节点
return target.getLeftNode() != null ? target.getLeftNode() : target.getRightNode();
}
/**
* 获取该节点左右子节点的个数
*
* @param node
* @return
*/
private int getChildNum(BSTreeNode node) {
int num = 0;
//存在左子节点
if (node.getLeftNode() != null) {
num++;
}
//存在右子节点
if (node.getRightNode() != null) {
num++;
}
return num;
}
/**
* 搜索
*
* @param key
* @return
*/
public BSTreeNode search(int key) {
if (null == root) {
return null;
}
BSTreeNode node = root;
while (node != null) {
int match = node.getKey();
if (key == match) {
return node;
}
if (key < match) {
node = node.getLeftNode();
} else {
node = node.getRightNode();
}
}
return null;
}
/**
* 搜索待删除节点的父节点
*
* @param key
* @return
*/
public BSTreeNode searchParent(int key) {
if (null == root) {
return null;
}
BSTreeNode temp = root;
while (temp != null) {
//跟它的子节点进行匹配,匹配任意一个都好使
if ((temp.getLeftNode() != null && temp.getLeftNode().getKey() == key)
|| (temp.getRightNode() != null && temp.getRightNode().getKey() == key)) {
return temp;
}
//不匹配的话,继续查找
int match = temp.getKey();
if (key < match) {
temp = temp.getLeftNode();
} else {
temp = temp.getRightNode();
}
}
return null;
}
/**
* 中序遍历
*/
public void midTraverse() {
if (root == null) {
return;
}
midTraverse(root);
}
/**
* 中序遍历
*
* @param node
*/
private void midTraverse(BSTreeNode node) {
if (node.getLeftNode() != null) {
midTraverse(node.getLeftNode());
}
System.out.println(node);
if (node.getRightNode() != null) {
midTraverse(node.getRightNode());
}
}
}
/**
* 测试代码
* @param args
*/
public static void main(String[] args) {
int[] array = new int[]{50, 30, 80, 20, 35, 34, 32, 40, 70, 75, 100};
BSTree tree = new BSTree();
for (int i = 0; i < array.length; i++) {
int key = array[i];
BSTreeNode node = new BSTreeNode(key);
tree.add(node);
}
System.out.println("中序遍历");
tree.midTraverse();
System.out.println("搜索20=" + tree.search(20));
System.out.println("搜索200=" + tree.search(200));
//删除节点
tree.delete(30);
System.out.println("中序遍历");
tree.midTraverse();
}