一、何为二叉搜索树
二叉搜索树是二叉树的一种,对于二叉搜索树中的每一个结点,它具有以下特点:
1. 结点的值大于左子树中所有结点的值
2. 结点的值小于右子树中所有结点的值
3. 满足递归定义,每一棵子树也是二叉搜索树
二、BST类定义
public class BST<E extends Comparable<E>> {
//结点类
private class TreeNode{
public E element;
public TreeNode right;
public TreeNode left;
public TreeNode(E element) {
this.element = element;
right = null;
left = null;
}
}
private TreeNode root; //跟结点
private int size = 0; //结点个数
//构造方法
public BST() {
root = null;
}
三、判断BST中是否包含某一元素
3.1 非递归实现
public boolean contains(E element) {
TreeNode current = root;
while(current != null) {
//元素小于当前结点的元素,则只需在左子树中进行判断
if(element.compareTo(current.element) < 0) {
current = current.left;
}
//元素大于当前结点的元素,则只需在右子树中进行判断
else if(element.compareTo(current.element) > 0) {
current = current.right;
}
else
return true; //当前结点的元素与要进行判断的元素值相等
}
return false;
}
3.2 递归实现
//判断树中是否包含某一元素
public boolean contains(E element) { //此方法展现给用户
return contains(root,element);
}
//递归实现详解,此方法用于内部实现
private boolean contains(TreeNode node, E element) {
if(node == null)
return false;
//元素小于当前结点元素,在左子树中递归遍历
if(element.compareTo(node.element) < 0) {
return contains(node.left, element);
}
//元素大于当前结点元素,在右子树中递归遍历
else if(element.compareTo(node.element) > 0)
return contains(node.right,element);
else //元素等于当前结点元素
return true;
}
四、BST的遍历
二叉树的前序、中序和后序遍历统称为广度优先遍历
二叉树的层序遍历也称为广度优先遍历
*************************************************************************************
4.1 前序遍历(递归实现 + 非递归实现)
4.1.1 递归实现
// 递归前序遍历
public void preOrder() {
preOrder(root);
}
private void preOrder(TreeNode node) {
if(node == null)
return;
System.out.print(node.element + " "); //访问当前结点
preOrder(node.left); //在左子树中进行遍历
preOrder(node.right); //在右子树中进行遍历
}
4.1.2 非递归实现
//非递归遍历
/*
* 思路: 1. 根结点先入栈
* 2. 判断栈是否为空,若为空则结束遍历;
* 若不为空,则弹出栈顶元素,然后访问栈顶元素
* 3. 若右孩子不为空,则右孩子入栈,否则执行第 4 步
* 4. 若左孩子不为空,则左孩子入栈,否则执行第 2 步,依次循环
* 注意: 左右孩子入栈顺序和遍历左右孩子的先后顺序正好相反
*/
public void preOrder() {
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()) {
TreeNode current = stack.pop();
System.out.println(current.element);
if(current.right != null)
stack.push(current.right);
if(current.left != null)
stack.push(current.left);
}
}
4.2 中序遍历(递归实现)
//2. 中序遍历
public void inOrder() {
inOrder(root);
}
private void inOrder(TreeNode node) {
if(node == null)
return;
inOrder(node.left);
System.out.print(node.element + " ");
inOrder(node.right);
}
4.3 后序遍历(递归实现)
public void postOrder() {
postOrder(root);
}
private void postOrder(TreeNode node) {
if(node == null)
return;
postOrder(node.left);
postOrder(node.right);
System.out.print(node.element + " ");
}
关于递归遍历的总结
递归的前序、中序和后序遍历的大致思路是一致的,只是访问根结点,遍历左子树,遍历右子树的顺序不同而已,需要注意的是:无论何种遍历方法,递归遍历左子树的操作一定在递归遍历右子树的操作的前面。
4.4 层序遍历(广度优先遍历)
/*
* 层序遍历(广度优先遍历)步骤:
* 1. 需要使用到队列,每次先使根结点入队
* 2. 判断队列是否为空
* 2.1 队列为空 说明树为空或遍历完成
* 2.2 队列非空,则执行出队操作,然后让当前结点的左孩子、右孩子依次入队
*/
public void levelOrder() {
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root); //根结点入队
while(!queue.isEmpty()) {
TreeNode current = queue.remove(); //出队
System.out.print(current.element + " ");
if(current.left != null)
queue.add(current.left); //左孩子入队
if(current.right != null)
queue.add(current.right); //右孩子入队
}
}
由于篇幅有点过长,关于BST的插入操作、删除操作,请参考我的其它博文,都有详细讲述。