上篇贴出了二分搜索树的C语言代码,这篇贴出二分搜索树的java实现代码。
public class BinarySearchTree<E extends Comparable<E>> { //一个泛型类型E需要实现一个接口的语法是使用extends关键字的
// 实现了Comparable这个借口的类视作可比较的类
//之后重写compareTo方法就可在内部自定义比较方式
private class Node{
public E e; //节点的值
public Node left,right; //二分搜索树的左节点和右节点
public Node(E e){
this.e = e;
this.left = null;
this.right = null;
}
}
private Node root; //根节点
private int size; //节点的个数
public BinarySearchTree(){
this.root = null;
this.size = 0;
}
//获取节点个数
public int getSize(){
return size;
}
//判断节点是否为空
public boolean isEmpty(){
return size == 0;
}
//向二分搜索树添加新的元素e
public void add(E e){
root = add(root,e);
}
//向以node为根节点的二分搜索树新的元素e,采用递归算法
//返回插入新节点后二分搜索树的根
private Node add(Node node,E e){
if(node == null){
size++;
return new Node(e);
}
if(e.compareTo(node.e) < 0) //由于e不是基础类型,不能直接用<或>比较,而E是满足Comparable接口的,所以使用compareTo方法比较
node.left = add(node.left,e);
else if(e.compareTo(node.e) > 0)
node.right = add(node.right,e);
return node;
}
//查看二分搜索树中是否包含元素e
public boolean contains(E e){
return contains(root,e);
}
//查看以node为根的二分搜索树中是否包含元素e
private boolean contains(Node node,E e){
if(node == null)
return false;
if(e.compareTo(node.e) == 0)
return true;
else if(e.compareTo(node.e) < 0)
return contains(node.left,e);
else
return contains(node.right,e);
}
//二分搜索树的前序遍历
public void preOrder(){
preOrder(root);
}
//前序遍历以node为根的二分搜索树
private void preOrder(Node node){
if(node == null)
return;
System.out.print(node.e);
preOrder(node.left);
preOrder(node.right);
}
//二分搜索树的中序遍历
public void inOrder(){
inOrder(root);
}
private void inOrder(Node node){
if(node == null)
return;
inOrder(node.left);
System.out.print(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.print(node.e);
}
//二分搜索树的前序遍历,采用非递归方法
public void preOrderNR(){
Stack<Node> stack = new ArrayStack<>();
stack.push(root);
while (!stack.isEmpty()){
Node cur = stack.pop();
System.out.print(cur.e);
if(cur.right != null)
stack.push(cur.right);
if(cur.left != null)
stack.push(cur.left);
}
}
//二分搜索树的层序遍历,广度优先,二分搜索树的前、中、后序遍历都是深度优先
public void levelOrder(){
Queue<Node> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()){
Node cur = queue.remove();
System.out.print(cur.e);
if(cur.left != null)
queue.add(cur.left);
if(cur.right != null)
queue.add(cur.right);
}
}
//寻找二分搜索树的最小元素
public E minimum(){
if(size == 0)
throw new IllegalArgumentException("这是一棵空树");
return minimum(root).e;
}
private Node minimum(Node node){
if(node.left == null)
return node;
return minimum(node.left);
}
//寻找二分搜索树的最大元素
public E maximum(){
if(size == 0)
throw new IllegalArgumentException("这是一棵空树");
return maximum(root).e;
}
private Node maximum(Node node){
if(node.right == null)
return node;
return maximum(node.right);
}
//删除二分搜索树中最小值所在的节点,并将最小值返回
public E removeMin(){
E ret = minimum();
root = removeMin(root);
return ret;
}
//删除以node为根的二分搜索树的最小节点
//返回删除节点后新的二分搜索树的根(有可能二分搜索树只有根节点和它的右子节点,此时删除了根节点后,需要返回新的节点作为根节点)
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;
}
//删除二分搜索树中最大值所在的节点,并将最大值返回
public E removeMax(){
E ret = maximum();
root = removeMax(root);
return ret;
}
//删除以node为根的二分搜索树的最大节点
//返回删除节点后新的二分搜索树的根
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;
}
//从二分搜索树中删除元素为e的节点
public void remove(E e){
root = remove(root,e);
}
//使用递归算法删除以node为根的二分搜索树的元素为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;
}
else if(e.compareTo(node.e) >0){
node.right = remove(node.right,e);
return node;
}
else { //e == node.e
//待删除节点的左子树为空,右子树不为空
if(node.left == null){
Node rightNode = node.right;
node.right = null;
size--;
return rightNode;
}
//待删除节点的右子树为空,左子树不为空
if(node.right == null){
Node leftNode = node.left;
node.left = null;
size--;
return leftNode;
}
//待删除节点的左右子树都不为空
//找到比待删除节点大的最小的节点,也就是待删除节点右子树的最小节点
//用找到的最小节点代替待删除节点的位置
Node successor = minimum(node.right); //successor 待删除节点的后继,也就是待删除节点右子树的最小节点
successor.right = removeMin(node.right);
successor.left = node.left;
node.left = node.right = null;
return successor;
}
}
public static void main(String[] args) {
BinarySearchTree<Integer> bst = new BinarySearchTree<>();
int[] nums = {5,3,7,8,6,4,2};
for (int num : nums) {
bst.add(num);
}
//二分搜索树的四种遍历
bst.preOrder();
System.out.println();
bst.inOrder();
System.out.println();
bst.postOrder();
System.out.println();
bst.preOrderNR();
System.out.println();
bst.levelOrder();
System.out.println();
System.out.println("--------------------------------------");
//删除最小节点
bst.removeMin();
bst.preOrder();
System.out.println();
//删除最大节点
bst.removeMax();
bst.preOrder();
System.out.println();
//删除指定的任意节点
bst.remove(5);
bst.preOrder();
}
}