版权声明:转载请注明出处: https://blog.csdn.net/qq_34774655/article/details/85321798
二分搜索树也是一种二叉树。
二分搜索树的遍历:
层序遍历图解:
删除任意元素图解:
代码实现:
package BST;
import java.util.LinkedList;
import java.util.Queue;
public class BinarySearchTree<E extends Comparable<E>> {
private class Node{
public E e;//数据域
public Node left,right;//指向左孩子、右孩子
/**
* 带参构造函数
* @param e
*/
public Node(E e) {
this.e=e;
left=null;
right=null;
}
}
private Node root;//根元素
private int size;//元素个数
/**
* 无参构造函数
*/
public BinarySearchTree() {
root=null;
size=0;
}
/**
* 获取元素个数
* @return
*/
public int size() {
return size;
}
/**
* 判断二分搜索树是否为空
* @return
*/
public boolean isEmpty() {
return size==0;
}
/**
* 向二分搜索树中添加新的元素e
* @param e
*/
public void add(E e) {
root=add(root,e);//调用内部的自定义的add方法
}
/**
* 向以node为根的二分搜索树中插入元素e,递归算法
* 返回插入新节点后二分搜索树的根
* @param node
* @param e
* @return
*/
private Node add(Node node,E e) {
if(node==null) {//基本问题
node=new Node(e);
size++;
}
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;
}
/**
* 看二分搜索树中是否包含元素e
* @param e
* @return
*/
public boolean contains(E e) {
return contains(root,e);
}
/**
* 看以node为根的二分搜索树中是否包含元素e, 递归算法
* @param node
* @param e
* @return
*/
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为根的二分搜索树, 递归算法
* @param node
*/
private void preOrder(Node node) {
if(node==null) {
return;
}
System.out.println(node.e);
preOrder(node.left);
preOrder(node.right);
}
/**
* 二分搜索树的中序遍历
*/
public void inOrder() {
inOrder(root);
}
/**
* 中序遍历以node为根的二分搜索树, 递归算法
* @param node
*/
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);
}
/**
* 后序遍历以node为根的二分搜索树, 递归算法
* @param node
*/
private void postOrder(Node node) {
if(node==null) {
return;
}
postOrder(node.left);
postOrder(node.right);
System.out.println(node.e);
}
/**
* 二分搜索树的层序遍历
*/
public void levelOrder() {
if(root==null) {
return;
}
//使用队列
Queue<Node> q=new LinkedList<Node>();
q.add(root);//添加到队尾
while(!q.isEmpty()) {
Node cur=q.remove();//移除队头元素
System.out.println(cur.e);
if(cur.left!=null) {
q.add(cur.left);
}
if(cur.right!=null) {
q.add(cur.right);
}
}
}
/**
* 获取二分搜索树的最小元素
* @return
*/
public E minimum() {
if(size == 0) {
throw new IllegalArgumentException("二分搜索树为空");
}
return minimum(root).e;
}
/**
* 返回以node为根的二分搜索树的最小值所在的节点
*递归算法
* @param node
* @return
*/
private Node minimum(Node node) {
if(node.left==null) {
return node;
}
return minimum(node.left);
}
/**
* 获取二分搜索树的最大元素
* @return
*/
public E maximum(){
if(size == 0)
throw new IllegalArgumentException("BST is empty");
return maximum(root).e;
}
/**
* 返回以node为根的二分搜索树的最大值所在的节点
* 递归算法
* @param node
* @return
*/
private Node maximum(Node node){
if( node.right == null )
return node;
return maximum(node.right);
}
/**
* 从二分搜索树中删除最小值所在节点, 返回最小值
* @return
*/
public E removeMin() {
E min=minimum();
root=removeMin(root);//删除的内部实现
return min;
}
/**
* 删除掉以node为根的二分搜索树中的最小节点
*返回删除节点后新的二分搜索树的根
* @param node
* @return
*/
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=maximum();
root=removeMax(root);
return max;
}
/**
* 删除掉以node为根的二分搜索树中的最大节点
*返回删除节点后新的二分搜索树的根
* @param node
* @return
*/
private Node removeMax(Node node) {
if(node.right==null) {
Node leftNode=node.left;
node=null;
return leftNode;
}
node.right=removeMax(node.right);
return node;
}
/**
* 从二分搜索树中删除元素为e的节点
* @param e
* @return
*/
public void remove(E e) {
root=remove(root,e);
}
/**
* 删除掉以node为根的二分搜索树中值为e的节点, 递归算法
*返回删除节点后新的二分搜索树的根
* @param node
* @param e
* @return
*/
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.compareTo(node.e) == 0
// 待删除节点左子树为空的情况
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.right=removeMin(node.right);
successor.left=node.left;
node.left=node.right=null;
return successor;
}
}
}
测试:
package BST;
import java.util.ArrayList;
import java.util.Random;
public class Test {
public static void main(String[] args) {
BinarySearchTree<Integer> bst=new BinarySearchTree<Integer>();
//测试添加
int[] nums = {5, 3, 6, 8, 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.levelOrder();
System.out.println();
//测试获取最大值
System.out.println(bst.maximum());
//测试删除最小值
Random random=new Random();
for(int i=0;i<100;i++) {
bst.add(random.nextInt(10000));
}
ArrayList<Integer> arrNums=new ArrayList<Integer>();
while(!bst.isEmpty()) {
arrNums.add(bst.removeMin());
}
System.out.println(arrNums);
}
}
控制台输出:
5
3
2
4
6
8
2
3
4
5
6
8
2
4
3
8
6
5
5
3
6
2
4
8
8
[2, 3, 4, 5, 6, 8, 108, 112, 287, 305, 321, 746, 764, 800, 911, 975, 1019, 1242, 1317, 1385, 1392, 1500, 1501, 1656, 1668, 1677, 1741, 1825, 1852, 2144, 2202, 2223, 2429, 2573, 2843, 2883, 2903, 3057, 3117, 3212, 3518, 3679, 3798, 3821, 3844, 3905, 3961, 3966, 4077, 4361, 4637, 4818, 5079, 5192, 5217, 5225, 5283, 5478, 5513, 5547, 5566, 5604, 5643, 5667, 5751, 5909, 5956, 6123, 6321, 6344, 6383, 6556, 6589, 6803, 6845, 6996, 7086, 7136, 7218, 7227, 7243, 7558, 7688, 7742, 7912, 7949, 8042, 8158, 8238, 8360, 8426, 8486, 8586, 8656, 8947, 8955, 9414, 9458, 9540, 9654, 9676, 9678, 9737, 9817, 9860, 9953]