前言
二叉排序树,又称二叉查找树、二叉搜索树。具有如下性质:当其不为空时,任何一个非叶子结点,左子结点的值比当前结点的值小,右子结点的值比当前结点的值大。
本文仅记录二叉排序树的Java实现,包括二叉排序树的创建、删除结点、中序遍历、查询结点等,话不多说直接上代码。
完整代码
public class BinarySortTree<T extends Comparable<T>> {
/**
* 根节点
*/
private Node<T> root;
public Node<T> getRoot() {
return root;
}
/**
* 添加结点
*
* @param newValue 待添加的新值
*/
public void add(T newValue) {
if (null == root) {
root = new Node<>(newValue);
} else {
add(newValue, root);
}
}
/**
* 添加结点
*
* @param newValue 要添加的新值
* @param root 二叉排序树的根节点
*/
private void add(T newValue, Node<T> root) {
if (null == newValue || null == root) {
return;
}
if (newValue.compareTo(root.value) < 0) {
if (null == root.left) {
root.left = new Node<>(newValue);
} else {
add(newValue, root.left);
}
} else {
if (null == root.right) {
root.right = new Node<>(newValue);
} else {
add(newValue, root.right);
}
}
}
/**
* 中序遍历二叉排序树
*/
public void infixOrder() {
infixOrder(root);
}
private void infixOrder(Node<T> root) {
if (null == root) {
return;
}
infixOrder(root.left);
System.out.println(root);
infixOrder(root.right);
}
public void delete(T targetValue) {
//在search方法中对root==null已经处理过,不需要再次处理
//寻找目标节点
Node<T> targetNode = search(targetValue);
//没有找到要删除的节点
if (targetNode == null) {
return;
}
//寻找目标节点的父节点
Node<T> parent = searchParent(targetValue);
//当目标节点为叶子节点
if (isLeaf(targetNode)) {
//当二叉排序树有且仅有一个节点
if (parent == null) {
root = null;
} else {
//目标节点是父节点的左子节点
if (isLeftNode(parent, targetValue)) {
parent.left = null;
}
//目标节点是父节点的右子结点
else if (isRightNode(parent, targetValue)) {
parent.right = null;
}
}
}
//当目标节点拥有两个子树
else if (targetNode.left != null && targetNode.right != null) {
T minValue = getMinValue(targetNode.right);
delete(minValue);
targetNode.value = minValue;
}
//当目标节点只有一个子树
else {
//当目标节点为根节点
if (parent == null) {
if (targetNode.left != null) {
root = targetNode.left;
} else {
root = targetNode.right;
}
} else {
//目标节点是父节点的左子节点
if (isLeftNode(parent, targetValue)) {
//目标节点拥有左子节点
if (targetNode.left != null) {
parent.left = targetNode.left;
} else {
parent.left = targetNode.right;
}
}
//目标节点是父节点的右子节点
else if (isRightNode(parent, targetValue)) {
if (targetNode.left != null) {
parent.right = targetNode.left;
} else {
parent.right = targetNode.right;
}
}
}
}
}
public T getMinValue() {
return getMinValue(root);
}
/**
* 查找以node节点为根节点的二叉搜索树的最小值
*
* @param root 二叉搜索树的根节点
* @return 当根节点不为null时返回该二叉搜索树的最小值
*/
private T getMinValue(Node<T> root) {
if (null == root) {
throw new RuntimeException("空树");
}
while (null != root.left) {
root = root.left;
}
return root.value;
}
/**
* 判断目标节点是否为叶子节点
*
* @param node 目标节点
* @return 如果是叶子节点则返回true,否则返回false
*/
private boolean isLeaf(Node<T> node) {
return node != null && node.left == null && node.right == null;
}
/**
* 判断nodeValue是否为parent节点的左子节点
*
* @param parent 父节点
* @param value 左子节点值
* @return 如果nodeValue是parent节点的左子节点则返回true,否则返回false
*/
private boolean isLeftNode(Node<T> parent, T value) {
return parent != null && parent.left != null && value.equals(parent.left.value);
}
/**
* 判断nodeValue是否为parent节点的右子节点
*/
private boolean isRightNode(Node<T> parent, T value) {
return parent != null && parent.right != null && value.equals(parent.right.value);
}
/**
* 查找目标结点
*
* @param target 查找的目标结点值
* @return 如果找到目标结点则返回该结点,否则返回null
*/
public Node<T> search(T target) {
return search(target, root);
}
private Node<T> search(T target, Node<T> root) {
if (root == null) {
return null;
}
if (target.equals(root.value)) {
return root;
} else if (target.compareTo(root.value) < 0) {
return search(target, root.left);
} else {
return search(target, root.right);
}
}
/**
* 查找目标结点的父节点
*
* @param target 目标结点值
* @return 如果找到目标节点的父节点则返回父节点,否则返回null
*/
public Node<T> searchParent(T target) {
return searchParent(target, root);
}
private Node<T> searchParent(T target, Node<T> pointer) {
if (pointer == null) {
return null;
}
//判断左子结点是否为目标值
boolean isTargetLeft = pointer.left != null && target.equals(pointer.left.value);
//判断右子结点是否为目标值
boolean isTargetRight = pointer.right != null && target.equals(pointer.right.value);
if (isTargetLeft || isTargetRight) {
return pointer;
} else {
if (target.compareTo(pointer.value) < 0) {
return searchParent(target, pointer.left);
} else {
return searchParent(target, pointer.right);
}
}
}
static class Node<T extends Comparable<T>> {
T value;
Node<T> left;
Node<T> right;
public Node(T data) {
this.value = data;
}
@Override
public String toString() {
return "Node{" +
"data=" + value +
'}';
}
}
}