二叉查找树的java语言实现
二叉查找树是什么?
二叉查找树是一个树节点拥有不超过两个子节点的树,它的左子树节点的数据小于它本身的数据,它的右子树节点的数据大于它本身节点的数据,每一个的节点包含一个数据,我们在这里先假设这里面的每一个数据都是不相同的,为了方便后面的插入与删除操作。
二叉树的节点的实现
因为是二叉查找树,所以节点是私有的,不能被公开。
代码实现如下:
private static class BinaryNode<Item>{
Item element;
BinaryNode left;
BinaryNode right;
BinaryNode(Item element){
this(element,null,null);
}
public BinaryNode(Item element, BinaryNode left, BinaryNode right) {
this.element = element;
this.left = left;
this.right = right;
}
}
关于二叉查找树里面的可以进行的操作
因为叫做二叉查找树,所以可以进行的操作主要以查找为主。
进行查找操作的方法介绍
- contain方法,看是否有这个数据包含在里面,如果有返回true,否则返回false;
- makeEmpty方法,是这颗树变为空树。
- isEmpty方法,看这棵树是否为空。
- findMin方法,找到这颗树的最小节点,可以通过根节点一直往左递归进行查找,直到递归到节点的左子树为空就找到了最小的节点。
- findMax方法,找到这棵树的最大节点,和找到最小节点的方法是一样的,只是这个是向右递归查找。
- insert方法,插入一个节点数据,注意当树里面有和节点数据相同的时,可以不做任何操作,也可以在附加域上做一个标记,例如有两个相同的数据,就实现2的附加域。
- remove方法,删除一个指定数据的节点,1:如果是一个树叶,就可以直接删除;2:如果这个节点有一个子树,就可以用这颗子树来代替删除的节点位置;3:如果有两颗子树,就用右子树里面的最小节点的数据来代替删除节点的数据,然后在通过递归删除右子节点的最小节点的数据,因为最小节点没有子树,所以很好删除,但是这个效率比较低,因为要进行两遍树的结点的查找。如图1:
- height方法,求树的高度的方法,注意当为一个树叶时,树的高度为0,所以树为空时,树的高度为-1。
进行树的遍历操作的方法介绍
- 树的遍历是通过递归的方法来进行处理的,可以有三种常见的方法:
- 前序遍历:先输出结点,在进行左右结点的输出。图片
- 中序遍历:先输出左节点,在输出结点,在输出右结点。
- 后序遍历:先输出左右结点,在进行结点的输出。
二叉查找树的代码实现
package com.ranyu.tree;
/**
* @version 1.0
* @Author ran_yu
* @Date 2023/01/29 10:36
**/
public class BinarySearchTree<Item extends Comparable<? super Item>> {
private static class BinaryNode<Item> {
Item element;
BinaryNode<Item> left;
BinaryNode<Item> right;
BinaryNode(Item element) {
this(element, null, null);
}
BinaryNode(Item element, BinaryNode<Item> left, BinaryNode<Item> right) {
this.element = element;
this.left = left;
this.right = right;
}
}
private BinaryNode<Item> root;//代表树的根结点
public BinarySearchTree() {
root = null;//此时先将根结点设置为空
}
/**
* 判断树是否为空
*
* @return
*/
public boolean isEmpty() {
return root == null;
}
/**
* 使树为空
*/
public void makeEmpty() {
root = null;
}
/**
* 判断是否包含这个元素
*
* @param element
* @return
*/
public boolean contains(Item element) {
return contains(element, root);
}
/**
* 这是contains 方法的私有实现
*
* @param element
* @param root
* @return
*/
private boolean contains(Item element, BinaryNode<Item> root) {
if (root == null) {//首先先判断是否为空
return false;
}
int result = element.compareTo(root.element);
if (result < 0) {//如果小于,就往左递归
return contains(element, root.left);
} else if (result > 0) {//如果大于,就往右递归
return contains(element, root.right);
} else {
return true;
}
}
/**
* 查找结点的最小值实现的是递归查找
*
* @return
*/
public Item findMin() {
if (isEmpty()) {
return null;
}
return findMin(root).element;
}
/**
* 查找findMin 的私有方法
*
* @param root
* @return
*/
private BinaryNode<Item> findMin(BinaryNode<Item> root) {
if (root == null) {
return null;
} else if (root.left == null) {//如果结点的左结点为空,此时它就是最小的结点
return root;
}
return findMin(root.left);//如果左结点不为空,在一直进行左字结点的遍历
}
/**
* 对找最大元素实现的是循环查找
*
* @return
*/
public Item findMax() {
if (isEmpty()) {
return null;
}
return findMax(root).element;
}
private BinaryNode<Item> findMax(BinaryNode<Item> root) {
if (root == null) {
return null;
}
while (root.right != null) {
root = root.right;
}
return root;
}
/**
* 进行元素的插入操作
*
* @param theElement
*/
public void insert(Item theElement) {
root = insert(theElement, root);
}
/**
* 插入操作的私有方法
*
* @param theElement
* @param root
* @return
*/
private BinaryNode<Item> insert(Item theElement, BinaryNode<Item> root) {
if (root == null) {
return new BinaryNode<Item>(theElement, null, null);
}
int result = theElement.compareTo(root.element);
if (result < 0) {
root.left=insert(theElement, root.left);
} else if (result > 0) {
root.right=insert(theElement, root.right);
} else {
//当树里面有这个元素时,此时不做任何操作
}
return root;
}
/**
* 进行元素的删除方法
*
* @param theElement
*/
public void remove(Item theElement) {
root = remove(theElement, root);
}
/**
* 进行元素删除的私有方法
*
* @param theElement
* @param root
* @return
*/
private BinaryNode<Item> remove(Item theElement, BinaryNode<Item> root) {
if (root == null) {
return null;
}
int result = theElement.compareTo(root.element);
if (result < 0) {
root.left= remove(theElement, root.left);
} else if (result > 0) {
root.right= remove(theElement, root.right);
} else if (root.left != null && root.right != null) {
root.element = findMin(root.right).element;//得到右子树的最小元素
root.right = remove(root.element, root.right);//此时就去删除右子树的最小结点,因为最小结点没有左子树和右子树,所以可以直接删除。
} else {//这里是判断当只有一个子树,或者没有子树的情形。
root = (root.left != null) ? root.left : root.right;
}
return root;
}
/**
* 进行前序遍历
*/
public void frontPrintTree() {
if (isEmpty()) {
System.out.println("empty tree");//表示为空树
} else {
frontPrintTree(root);
}
}
private void frontPrintTree(BinaryNode<Item> root) {
if (root != null) {
System.out.print(root.element + " ");
frontPrintTree(root.left);
frontPrintTree(root.right);
}
}
/**
* 中序遍历的实现
*/
public void midPrintTree() {
if (isEmpty()) {
System.out.println("empty tree");
} else {
midPrintTree(root);
}
}
private void midPrintTree(BinaryNode<Item> root) {
if (root != null) {
midPrintTree(root.left);
System.out.print(root.element + " ");
midPrintTree(root.right);
}
}
/**
* 后序遍历的实现
*/
public void laterPrintTree() {
if (isEmpty()) {
System.out.println("empty tree");
} else {
midPrintTree(root);
}
}
private void laterPrintTree(BinaryNode<Item> root) {
if (root != null) {
laterPrintTree(root.left);
laterPrintTree(root.right);
System.out.print(root.element + " ");
}
}
/**
* 求树的高度
*
* @return
*/
public int height() {
return height(root);
}
private int height(BinaryNode<Item> root) {
if (root == null) {
return -1;
}
return 1 + Math.max(height(root.left), height(root.right));
}
}
进行测试
public static void main(String[] args) {
BinarySearchTree<Integer> tree = new BinarySearchTree<>();
int[] arr={13,5,7,8,14,11,20,9,22,15};
for (int i = 0; i < arr.length; i++) {
tree.insert(arr[i]);
}
//测试树是否为空
if(tree.isEmpty()){
System.out.println("树为空");
}else {
System.out.println("树不为空");
}
int value=15;
//测试包含方法是否可行
if(tree.contains(value)){
System.out.println("树中包含"+value);
}else {
System.out.println("树中不存在");
}
//测试找最小值
Integer min = tree.findMin();
System.out.println("最小值为: "+min);
//测试找最大值
Integer max = tree.findMax();
System.out.println("最大值为: "+max);
//进行遍历测试
System.out.println("前序遍历");
tree.frontPrintTree();
System.out.println("中序遍历");
tree.midPrintTree();
System.out.println("后序遍历");
tree.laterPrintTree();
//测试树的高度
int height = tree.height();
System.out.println("高度为:"+height);
//删除元素
int deleteValue=15;
System.out.println("删除前");
tree.frontPrintTree();
tree.remove(deleteValue);
System.out.println("删除后");
tree.frontPrintTree();
}
输出结果为:
- 树不为空
- 树中包含15
- 最小值为: 5
- 最大值为: 22
- 前序遍历
- 13 5 7 8 11 9 14 20 15 22
- 中序遍历
- 5 7 8 9 11 13 14 15 20 22
- 后序遍历
- 5 7 8 9 11 13 14 15 20 22
- 高度为:5
- 删除前
- 13 5 7 8 11 9 14 20 15 22
- 删除后
- 13 5 7 8 11 9 14 20 22