二叉搜索树的插入、删除、查找等操作:Java语言实现
1 二叉搜索树介绍
二叉搜索树(BST, Binary Search Tree),也称二叉排序树或二叉查找树。
二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:
1. 非空左子树的所有键值小于其根结点的键值。
2. 非空右子树的所有键值大于其根结点的键值。
3. 左、右子树都是二叉搜索树。
2 二叉搜索树的主要操作
若搜索树非空,则根结点关键字和X进行比较, 并进行不同处理:
若X小于根结点键值,只需在左子树中继续搜索;
如果X大于根结点的键值, 在右子树中进行继续搜索;
若两者比较结果是相等,搜索完成,返回指向此结点的指针。
//查找元素:递归方法
BinarySearchTreeNode find(BinarySearchTreeNode root, int data) {
if (root == null)
return null;//查询失败
if (data < root.getData())
return find(root.getLeft(),data);//在左子树中继续查找
else if (data > root.getData())
return find(root.getRight(),data);//在右子树中继续查找
else
return root;//查找成功, 返回找到的结点的地址
}
//查找元素:非递归方法
BinarySearchTreeNode iterFind(BinarySearchTreeNode root, int data) {
while (root != null) {
if (data < root.getData())
root = root.getLeft();//向左子树中移动, 继续查找
else if (data > root.getData())
root = root.getRight();//向右子树中移动, 继续查找
else
return root;//查找成功, 返回找到的结点的地址
}
return null;//查询失败
}
2.2 查找最大和最小元素
最大元素一定是在树的最右分枝的端结点上
最小元素一定是在树的最左分枝的端结点上
//查找最小元素:递归方法 (最小元素一定是在树的最左分枝的端结点上)
BinarySearchTreeNode findMin(BinarySearchTreeNode root) {
if (root == null)
return null;//空的二叉搜索树,返回null
else if (root.getLeft() == null)
return root;//找到最左叶结点并返回
else
return findMin(root.getLeft());//沿左分支继续查找
}
//查找最小元素:非递归方法 (最小元素一定是在树的最左分枝的端结点上)
BinarySearchTreeNode iterFindMin(BinarySearchTreeNode root) {
if (root == null)
return null;//空的二叉搜索树,返回null
while (root.getLeft() != null)
root = root.getLeft();//沿左分支继续查找
return root;//找到最左叶结点并返回
}
//查找最大元素:递归方法 (最大元素一定是在树的最右分枝的端结点上)
BinarySearchTreeNode findMax(BinarySearchTreeNode root) {
if (root == null)
return null;//空的二叉搜索树,返回null
else if (root.getRight() == null)
return root;//找到最右叶结点并返回
else
return findMax(root.getRight());//沿右分支继续查找
}
//查找最大元素:非递归方法 (最大元素一定是在树的最右分枝的端结点上)
BinarySearchTreeNode iterFindMax(BinarySearchTreeNode root) {
if (root == null)
return null;//空的二叉搜索树,返回null
while (root.getRight() != null)
root = root.getRight();//沿右分支继续查找
return root;//找到最右叶结点并返回
}
2.3 二叉搜索树的插入将元素X插入二叉搜索树BST中,关键是要找到元素应该插入的位置。位置的确定可以利用与查找函数Find类似的方法,如果在树BST中找到X,说明要插入的元素已存在,可放弃插入操作。如果没找到X,查找终止的位置就是X应插入的位置。
//插入元素
BinarySearchTreeNode insert(BinarySearchTreeNode root, int data) {
if (root == null)
root = new BinarySearchTreeNode(data);//若原树为空, 生成并返回一个结点的二叉搜索树
else {
if (data < root.getData()) //开始找要插入元素的位置
root.setLeft(insert(root.getLeft(),data));//递归插入左子树
else if (data > root.getData())
root.setRight(insert(root.getRight(),data));//递归插入右子树
}
return root;
}
2.4 二叉搜索树的删除
考虑三种情况:
要删除的是叶结点: 直接删除, 并再修改其父结点指针---置为null
要删除的结点只有一个孩子结点: 将其父结点的指针指向要删除结点的孩子结点
//删除元素
BinarySearchTreeNode delete(BinarySearchTreeNode root, int data) {
BinarySearchTreeNode temp;
if (root == null)
System.out.println("要删除的元素未找到");
else if (data < root.getData())
root.setLeft(delete(root.getLeft(),data));//左子树递归删除
else if (data > root.getData())
root.setRight(delete(root.getRight(),data));//右子树递归删除
else { //找到要删除的结点
if (root.getLeft() != null && root.getRight() != null) { //被删除结点有左右两个子结点
temp = findMin(root.getRight());//在右子树中找最小的元素填充删除结点
root.setData(temp.getData());
root.setRight(delete(root.getRight(),root.getData()));//在删除结点的右子树中删除最小元素
}else { //被删除结点有一个或无子结点
temp = root;
if (root.getLeft() == null) //有右孩子或无子结点
root = root.getRight();
else if (root.getRight() == null) //有左孩子或无子结点
root = root.getLeft();
temp = null;
}
}
return root;
}
2.5 二叉搜索树的遍历
二叉搜索树的遍历,与普通的二叉树的遍历一样。不太懂的,可以看下我的这两篇文章,《二叉树的非递归遍历:Java语言实现》、《二叉树的递归遍历:Java语言实现》。
需要注意的是:中序遍历二叉搜索树时,将得到一个有序表。
//中序遍历:递归方法 (中序遍历二叉搜索树时,将得到一个有序表)
void InOrderRecursive(BinarySearchTreeNode root) {
if(root == null)
return;
InOrderRecursive(root.getLeft());//中序遍历其左子树
System.out.print(root.getData() + " ");//访问根结点
InOrderRecursive(root.getRight());//中序遍历其右子树
}
3 Java整体代码实现
3.1 建立二叉搜索树结点类
package Binary_Tree_Study;
/**
* Created by Administrator on 2018/5/20.
*/
public class BinarySearchTreeNode {
private int data;//结点的数据
private BinarySearchTreeNode left;//指向左孩子结点
private BinarySearchTreeNode right;//指向左孩子结点
public BinarySearchTreeNode(int data) {
this.data = data;
this.left = null;
this.right =null;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public BinarySearchTreeNode getLeft() {
return left;
}
public void setLeft(BinarySearchTreeNode left) {
this.left = left;
}
public BinarySearchTreeNode getRight() {
return right;
}
public void setRight(BinarySearchTreeNode right) {
this.right = right;
}
}
3.2 二叉搜索树的上述操作代码实现
package Binary_Tree_Study;
/**
* Created by Administrator on 2018/5/20.
*/
public class BinarySearchTree {
private BinarySearchTreeNode root;//根结点
public BinarySearchTree() {
this.root = null;
}
//查找元素:递归方法
BinarySearchTreeNode find(BinarySearchTreeNode root, int data) {
if (root == null)
return null;//查询失败
if (data < root.getData())
return find(root.getLeft(),data);//在左子树中继续查找
else if (data > root.getData())
return find(root.getRight(),data);//在右子树中继续查找
else
return root;//查找成功, 返回找到的结点的地址
}
//查找元素:非递归方法
BinarySearchTreeNode iterFind(BinarySearchTreeNode root, int data) {
while (root != null) {
if (data < root.getData())
root = root.getLeft();//向左子树中移动, 继续查找
else if (data > root.getData())
root = root.getRight();//向右子树中移动, 继续查找
else
return root;//查找成功, 返回找到的结点的地址
}
return null;//查询失败
}
//查找最小元素:递归方法 (最小元素一定是在树的最左分枝的端结点上)
BinarySearchTreeNode findMin(BinarySearchTreeNode root) {
if (root == null)
return null;//空的二叉搜索树,返回null
else if (root.getLeft() == null)
return root;//找到最左叶结点并返回
else
return findMin(root.getLeft());//沿左分支继续查找
}
//查找最小元素:非递归方法 (最小元素一定是在树的最左分枝的端结点上)
BinarySearchTreeNode iterFindMin(BinarySearchTreeNode root) {
if (root == null)
return null;//空的二叉搜索树,返回null
while (root.getLeft() != null)
root = root.getLeft();//沿左分支继续查找
return root;//找到最左叶结点并返回
}
//查找最大元素:递归方法 (最大元素一定是在树的最右分枝的端结点上)
BinarySearchTreeNode findMax(BinarySearchTreeNode root) {
if (root == null)
return null;//空的二叉搜索树,返回null
else if (root.getRight() == null)
return root;//找到最右叶结点并返回
else
return findMax(root.getRight());//沿右分支继续查找
}
//查找最大元素:非递归方法 (最大元素一定是在树的最右分枝的端结点上)
BinarySearchTreeNode iterFindMax(BinarySearchTreeNode root) {
if (root == null)
return null;//空的二叉搜索树,返回null
while (root.getRight() != null)
root = root.getRight();//沿右分支继续查找
return root;//找到最右叶结点并返回
}
//插入元素
BinarySearchTreeNode insert(BinarySearchTreeNode root, int data) {
if (root == null)
root = new BinarySearchTreeNode(data);//若原树为空, 生成并返回一个结点的二叉搜索树
else {
if (data < root.getData()) //开始找要插入元素的位置
root.setLeft(insert(root.getLeft(),data));//递归插入左子树
else if (data > root.getData())
root.setRight(insert(root.getRight(),data));//递归插入右子树
}
return root;
}
//删除元素
BinarySearchTreeNode delete(BinarySearchTreeNode root, int data) {
BinarySearchTreeNode temp;
if (root == null)
System.out.println("要删除的元素未找到");
else if (data < root.getData())
root.setLeft(delete(root.getLeft(),data));//左子树递归删除
else if (data > root.getData())
root.setRight(delete(root.getRight(),data));//右子树递归删除
else { //找到要删除的结点
if (root.getLeft() != null && root.getRight() != null) { //被删除结点有左右两个子结点
temp = findMin(root.getRight());//在右子树中找最小的元素填充删除结点
root.setData(temp.getData());
root.setRight(delete(root.getRight(),root.getData()));//在删除结点的右子树中删除最小元素
}else { //被删除结点有一个或无子结点
temp = root;
if (root.getLeft() == null) //有右孩子或无子结点
root = root.getRight();
else if (root.getRight() == null) //有左孩子或无子结点
root = root.getLeft();
temp = null;
}
}
return root;
}
//中序遍历:递归方法 (中序遍历二叉搜索树时,将得到一个有序表)
void InOrderRecursive(BinarySearchTreeNode root) {
if(root == null)
return;
InOrderRecursive(root.getLeft());//中序遍历其左子树
System.out.print(root.getData() + " ");//访问根结点
InOrderRecursive(root.getRight());//中序遍历其右子树
}
//以下函数调用相应的方法
public void callFindMin() {
BinarySearchTreeNode cur = findMin(root);
System.out.println("\n最小元素为:" + cur.getData());
}
public void callIterFindMin() {
BinarySearchTreeNode cur = iterFindMin(root);
System.out.println("\n最小元素为:" + cur.getData());
}
public void callFindMax() {
BinarySearchTreeNode cur = findMax(root);
System.out.println("\n最大元素为:" + cur.getData());
}
public void callIterFindMax() {
BinarySearchTreeNode cur = iterFindMax(root);
System.out.println("\n最大元素为:" + cur.getData());
}
public void callInsert(int data) {
root = insert(root, data);
}
public void callDelete(int data) {
root = delete(root, data);
}
public void callInOrderRecursive() {
InOrderRecursive(root);
}
}
3.3 测试
package Binary_Tree_Study;
/**
* Created by Administrator on 2018/5/20.
*/
public class BinarySearchTreeTest {
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
/* 创建如下的二叉搜索树
5
/ \
3 7
/ \ / \
2 4 6 8 */
tree.callInsert(5);
tree.callInsert(3);
tree.callInsert(2);
tree.callInsert(4);
tree.callInsert(7);
tree.callInsert(6);
tree.callInsert(8);
System.out.println("中序遍历为:");
tree.callInOrderRecursive();//2 3 4 5 6 7 8
tree.callFindMin();//最小元素为:2
tree.callFindMax();//最大元素为:8
System.out.println("\nD删除结点数据 2");
tree.callDelete(2);
System.out.println("删除删除结点数据2后的中序遍历为:");
tree.callInOrderRecursive();//3 4 5 6 7 8
tree.callIterFindMin();//最小元素为:3
tree.callIterFindMax();//最大元素为:8
}
}
4 参考资料
[1] 浙大数据结构慕课
上一篇: 二叉搜索树(Binary Search Tree)
下一篇: 线性数据结构——顺序表