实现一个简单的二分搜索树,有如下功能
- 获取size
- 判断是否为空
- 添加元素
- 判断是否包含指定元素
- 前序遍历
- 非递归前序遍历
- 中序遍历
- 后序遍历
- 广度优先遍历
- 查找树中的最小值
- 查找树中的最大值
- 删除最小值
- 删除最大值
- 删除指定元素
练习源码
import java.util.LinkedList
import java.util.Stack
import java.util.Queue
/**
* 二分搜索树
*/
public class BST<E extends Comparable<E>> {
private class Node {
public E e
public Node left, right
public Node(E e) {
this.e = e
left = null
right = null
}
}
private Node root
private int size
public BST() {
root = null
size = 0
}
public int size() {
return size
}
public boolean isEmpty() {
return size == 0
}
public void add(E e) {
root = add(root, e)
}
/**
* 添加元素
*
* @param node Node
* @param e 要添加的元素
* @return 添加后的Node
*/
private Node add(Node node, E e) {
if (node == null) {
size++
return new Node(e)
}
if (e.compareTo(node.e) < 0) {
node.left = add(node.left, e)
} else if (e.compareTo(node.e) > 0) {
node.right = add(node.right, e)
}
return node
}
public boolean contains(E e) {
return contains(root, e)
}
private boolean contains(Node node, E e) {
if (node == null) {
return false
}
if (e.compareTo(node.e) == 0) {
return true
}
if (e.compareTo(node.e) < 0) {
return contains(node.left, e)
}
return contains(node.right, e)
}
/**
* 二叉搜索树的前序遍历
*/
public void preOrder() {
preOrder(root)
}
private void preOrder(Node node) {
if (node == null) {
return
}
System.out.println(node.e)
preOrder(node.left)
preOrder(node.right)
}
/**
* 非递归前序遍历
*/
public void preOrderNoRecursive() {
Stack<Node> stack = new Stack<>()
stack.push(root)
while (!stack.isEmpty()) {
Node cur = stack.pop()
System.out.println(cur.e)
if (cur.right != null) {
stack.push(cur.right)
}
if (cur.left != null) {
stack.push(cur.left)
}
}
}
/**
* 二叉搜索树的中序遍历
*/
public void inOrder() {
inOrder(root)
}
private void inOrder(Node node) {
if (node == null) {
return
}
inOrder(node.left)
System.out.println(node.e)
inOrder(node.right)
}
/**
* 二叉搜索树的后序遍历
*/
public void postOrder() {
postOrder(root)
}
private void postOrder(Node node) {
if (node == null) {
return
}
postOrder(node.left)
postOrder(node.right)
System.out.println(node.e)
}
/**
* 二叉搜索树的广度优先遍历
*/
public void levelOrder() {
Queue<Node> queue = new LinkedList<>()
queue.add(root)
while (!queue.isEmpty()) {
Node cur = queue.remove()
System.out.println(cur.e)
if (cur.left != null) {
queue.add(cur.left)
}
if (cur.right != null) {
queue.add(cur.right)
}
}
}
/**
* 查找二叉搜索树中的最小值
*
* @return 最小值
*/
public E findMin() {
if (size == 0) {
throw new IllegalArgumentException("tree is empty")
}
return findMin(root).e
}
private Node findMin(Node node) {
if (node.left == null) {
return node
}
return findMin(node.left)
}
/**
* 查找二叉搜索树中的最大值
*
* @return 最大值
*/
public E findMax() {
if (size == 0) {
throw new IllegalArgumentException("tree is empty")
}
return findMax(root).e
}
private Node findMax(Node node) {
if (node.right == null) {
return node
}
return findMax(node.right)
}
/**
* 删除最小值
*
* @return 删除的最小值
*/
public E removeMin() {
E min = findMin()
root = removeMin(root)
return min
}
private Node removeMin(Node node) {
if (node.left == null) {
Node rightNode = node.right
node.right = null
size--
return rightNode
}
node.left = removeMin(node.left)
return node
}
/**
* 删除最大值
*
* @return 删除的最大值
*/
public E removeMax() {
E max = findMax()
root = removeMax(root)
return max
}
private Node removeMax(Node node) {
if (node.right == null) {
Node leftNode = node.left
node.left = null
size--
return leftNode
}
node.right = removeMax(node.right)
return node
}
/**
* 删除指定元素
*
* @param e 要删除的元素
*/
public void remove(E e) {
root = remove(root, e)
}
private Node remove(Node node, E e) {
if (node == null) {
return null
}
if (e.compareTo(node.e) < 0) {
node.left = remove(node.left, e)
return node
}
if (e.compareTo(node.e) > 0) {
node.right = remove(node.right, e)
return node
}
if (node.left == null) {
// 要删除的元素左节点为null
Node rightNode = node.right
node.right = null
size--
return rightNode
}
if (node.right == null) {
// 要删除的元素右节点为null
Node leftNode = node.left
node.left = null
size--
return leftNode
}
// 待删除元素左右节点子树均不为空
// 找到比待删除节点大的最小节点,即待删除节点右子树的最小节点
// 用这个节点顶替待删除节点的位置
Node successor = findMin(node.right)
successor.right = removeMin(node.right)
successor.left = node.left
node.left = node.right = null
return successor
}
@Override
public String toString() {
StringBuilder res = new StringBuilder()
generateTreeString(root, 0, res)
return res.toString()
}
private void generateTreeString(Node node, int depth, StringBuilder res) {
if (node == null) {
res.append(generateDepthString(depth)).append("null\n")
return
}
res.append(generateDepthString(depth)).append(node.e).append("\n")
generateTreeString(node.left, depth + 1, res)
generateTreeString(node.right, depth + 1, res)
}
private String generateDepthString(int depth) {
// JDK11 语法
return "--".repeat(Math.max(0, depth))
}
public static void main(String[] args) {
BST<Integer> tree = new BST<>()
int[] nums = {1, 7, 3, 6, 2, 8, 11, 2}
for (int num : nums) {
tree.add(num)
}
System.out.println(tree)
}
}