目录
完整代码已上传至gitee中:gitee代码仓库
二叉查找树
二叉查找树,又称二叉排序树,亦称二叉搜索树,是数据结构中的一类。在一般情况下,查找效率比链表结构要高。
二叉查找树的定义:
一棵空树或具有如下性质的树:
①若左子树不为空,则左子树上所有结点的值小于根结点的值;
②若右子树不为空,则右子树上所有结点的值大于根结点的值;
③左右子树也分别为二叉查找树
初始化
二叉查找树的初始化方式与二叉树一致.
public class TestBinarySearchTree {
private static class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
//初始化根结点,默认初始化为null
private TreeNode root;
}
二叉查找树的查找
①首先比较根结点,若根节点的关键字值等于查找的关键字值,则查找成功;
②若根节点的关键字值大于查找的关键字值,则查找左子树;
③若根节点的关键字值小于查找的关键字值,则查找右子树;
④若未查找到,则返回false,查找失败.
/**
* 二叉查找树的contains查找操作
* @param val
* @return
*/
public boolean contains(int val) {
if(root == null) {
return false;
}
TreeNode cur = root;
while(cur != null) {
if(cur.val == val) {
return true;
}else if(cur.val > val) {
cur = cur.left;
}else {
cur = cur.right;
}
}
return false;
}
二叉查找树的插入
①若二叉树为空,则单独生成根结点;
②若二叉树不为空,则查找待插入的值应该放入的位置,之后进行插入即可,具体步骤如下:
while(cur != null) {
if(cur.val < val) {
parent = cur;
cur = cur.right;
}else if(cur.val > val) {
parent = cur;
cur = cur.left;
}else {
return false;//不能插入相同的数字
}
}
之后比较parent.val与待插入值的大小来决定插入位置,具体代码如下:
/**
* 二叉查找树的插入
* @param val
* @return
*/
public boolean insert(int val) {
if(root == null) {
root = new TreeNode(val);
return true;
}
TreeNode cur = root;
TreeNode parent = null;
while(cur != null) {
if(cur.val < val) {
parent = cur;
cur = cur.right;
}else if(cur.val > val) {
parent = cur;
cur = cur.left;
}else {
return false;//不能插入相同的数字
}
}
if(parent.val < val) {
parent.right = new TreeNode(val);
}else {
parent.left = new TreeNode(val);
}
return true;
}
二叉查找树的删除
二叉查找树的删除操作,首先找到待删除的结点和其parent结点,之后进行删除操作:
1、当cur.left == null时:
①若cur是root,则令root = cur.right;
②若cur是parent.left,则parent.left = cur.right;
③若cur是parent.right,则parent.right = cur.right;
2、当cur.right == null时:
①若cur是root,则令root = cur.left;
②若cur是parent.left,则parent.left = cur.left;
③若cur是parent.right,则parent.right = cur.left;
3、如果不满足上列两个判断条件,则另外进行判断,具体代码如下:
/**
* 二叉查找树的删除
* @param val
* @return
*/
public boolean remove(int val) {
if(root == null) {
return false;
}
TreeNode cur = root;
TreeNode parent = null;
while(cur != null) {
if(cur.val < val) {
parent = cur;
cur = cur.right;
}else if(cur.val > val) {
parent = cur;
cur = cur.left;
}else {
removeNode(parent,cur);
return true;
}
}
return false;
}
public void removeNode(TreeNode parent, TreeNode cur) {
if(cur.left == null) {
if(cur == root) {
root = cur.right;
}else if(parent.right == cur) {
parent.right = cur.right;
}else {
parent.left = cur.right;
}
}else if(cur.right == null) {
if(cur == root) {
cur = cur.left;
}else if(parent.left == cur) {
parent.left = cur.left;
}else {
parent.right = cur.left;
}
}else {
TreeNode target = cur.right;
TreeNode targetParent = cur;
while(target != null) {
targetParent = target;
target = target.left;
}
cur.val = target.val;
if(target == targetParent.left) {
targetParent.left = target.right;
}else {
targetParent.right = target.right;
}
}
}
二叉查找树的中序遍历
即将从小到大排序后的数据输出
/**
* 二叉查找树的中序遍历
* @param root
*/
public void inorder(TreeNode root) {
if(root == null) {
return ;
}
inorder(root.left);
System.out.print(root.val + " ");
inorder(root.right);
}
findMax and findMin
根据分析可知,二叉查找树最左边一个结点为其最小值,最右边的一个结点为其最大值,则根据该性质,可以写出如下代码:
/**
* 输出二叉查找树中的最大值
* @param root
*/
public void findMax(TreeNode root) {
if(root == null) {
System.out.println("二叉查找树为空");
return ;
}
while(root.right != null) {
root = root.right;
}
System.out.println("最大值为:" + root.val);
}
/**
* 输出二叉查找树中的最小值
* @param root
*/
public void findMin(TreeNode root) {
if(root == null) {
System.out.println("二叉查找树为空");
return ;
}
while(root.left != null) {
root = root.left;
}
System.out.println("最小值为:" + root.val);
}
二叉查找树完整代码
public class TestBinarySearchTree {
private static class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
private TreeNode root;
/**
* 二叉查找树的contains操作
* @param val
* @return
*/
public boolean contains(int val) {
if(root == null) {
return false;
}
TreeNode cur = root;
while(cur != null) {
if(cur.val == val) {
return true;
}else if(cur.val > val) {
cur = cur.left;
}else {
cur = cur.right;
}
}
return false;
}
/**
* 二叉查找树的插入
* @param val
* @return
*/
public boolean insert(int val) {
if(root == null) {
root = new TreeNode(val);
return true;
}
TreeNode cur = root;
TreeNode parent = null;
while(cur != null) {
if(cur.val < val) {
parent = cur;
cur = cur.right;
}else if(cur.val > val) {
parent = cur;
cur = cur.left;
}else {
return false;//不能插入相同的数字
}
}
if(parent.val < val) {
parent.right = new TreeNode(val);
}else {
parent.left = new TreeNode(val);
}
return true;
}
/**
* 二叉查找树的删除
* @param val
* @return
*/
public boolean remove(int val) {
if(root == null) {
return false;
}
TreeNode cur = root;
TreeNode parent = null;
while(cur != null) {
if(cur.val < val) {
parent = cur;
cur = cur.right;
}else if(cur.val > val) {
parent = cur;
cur = cur.left;
}else {
removeNode(parent,cur);
return true;
}
}
return false;
}
public void removeNode(TreeNode parent, TreeNode cur) {
if(cur.left == null) {
if(cur == root) {
root = cur.right;
}else if(parent.right == cur) {
parent.right = cur.right;
}else {
parent.left = cur.right;
}
}else if(cur.right == null) {
if(cur == root) {
cur = cur.left;
}else if(parent.left == cur) {
parent.left = cur.left;
}else {
parent.right = cur.left;
}
}else {
TreeNode target = cur.right;
TreeNode targetParent = cur;
while(target != null) {
targetParent = target;
target = target.left;
}
cur.val = target.val;
if(target == targetParent.left) {
targetParent.left = target.right;
}else {
targetParent.right = target.right;
}
}
}
/**
* 二叉查找树的中序遍历
* @param root
*/
public void inorder(TreeNode root) {
if(root == null) {
return ;
}
inorder(root.left);
System.out.print(root.val + " ");
inorder(root.right);
}
/**
* 输出二叉查找树中的最大值
* @param root
*/
public void findMax(TreeNode root) {
if(root == null) {
System.out.println("二叉查找树为空");
return ;
}
while(root.right != null) {
root = root.right;
}
System.out.println("最大值为:" + root.val);
}
/**
* 输出二叉查找树中的最小值
* @param root
*/
public void findMin(TreeNode root) {
if(root == null) {
System.out.println("二叉查找树为空");
return ;
}
while(root.left != null) {
root = root.left;
}
System.out.println("最小值为:" + root.val);
}
}
测试用例
测试代码以及测试结果如下所示
public class TestDemo {
public static void main(String[] args) {
TestBinarySearchTree tree = new TestBinarySearchTree();
//创建二叉查找树
tree.insert(5);
tree.insert(8);
tree.insert(1);
tree.insert(10);
tree.insert(16);
tree.insert(3);
tree.insert(4);
System.out.println("二叉查找树的中序遍历");
tree.inorder(tree.root);
System.out.println("\n" + "===================");
System.out.println("二叉查找树的查找,查找16");
System.out.println(tree.contains(16));
System.out.println("\n" + "===================");
System.out.println("二叉查找树的插入,插入21");
tree.insert(21);
tree.inorder(tree.root);
System.out.println("\n" + "===================");
System.out.println("二叉查找树的删除,删除1");
tree.remove(1);
tree.inorder(tree.root);
System.out.println("\n" + "===================");
System.out.println("输出二叉查找树的最大值和最小值");
tree.findMax(tree.root);
tree.findMin(tree.root);
}
}
测试结果
二叉查找树的中序遍历
1 3 4 5 8 10 16
===================
二叉查找树的查找,查找16
true
===================
二叉查找树的插入,插入21
1 3 4 5 8 10 16 21
===================
二叉查找树的删除,删除1
3 4 5 8 10 16 21
===================
输出二叉查找树的最大值和最小值
最大值为:21
最小值为:3