目录
前言
一、二叉搜索树的概念
1.定义
2.特点
二、二叉搜索树的操作
1.查找操作
2.插入操作
3.删除操作
三、二叉搜索树的时间复杂度
完整代码
总结
在Java数据结构之二叉搜索树的学习中,我通过总结以及查阅资料,对以下问题有了更深一层的理解。
如果你在Java数据结构之二叉搜索树的学习中,也想对这些问题有一个更深的了解,请阅读这篇文章,或许会对你有所启发。
二叉搜索树又叫二叉排序树,它或是一颗空树,或是具有以下性质的二叉树
二叉搜索树中序遍历后会得到一个升序排列的数组,若是一棵树的中序遍历是一个升序排列的数组,也能说明这棵树是二叉搜索树,在二叉搜索树中,右子树的值永远大于左子树的值。
二、二叉搜索树的基本结构
public class TreeNode {
public long key;//要去寻找的结点
public TreeNode left;//左子树引用
public TreeNode right;//右子树引用
public TreeNode(long key){
this.key=key;
}
public String toString(){
return String.format("TreeNode(%d)",key);
}
}
根据二叉搜索树的定义,我们可知左子树的值要小于根节点的值,右子树的值要大于根节点的值,则我们
//查找操作
public boolean contains(long key) {
TreeNode cur = root;
while (cur != null) {//当前节点不为空
if (key == cur.key) {
return true;
} else if (key < cur.key) {
//如果要找的数小于当前节点值,就去左子树找
cur = cur.left;
} else {
//key>cur.key
//如果要找的数大于当前节点值,就去右子树找
cur = cur.right;
}
}
//如果整棵树遍历结束都找不到,则返回false
return false;
}
在二叉搜索树中插入一个元素,首先要找到一个合适的插入位置,插入的新结点必须出现在原来空的地方
//插入操作
//如果key重复了,那么插入操作可能会失败
public boolean add(long key) {
//定义结点
TreeNode node = new TreeNode(key);
if (this.root == null) {
//如果根节点为空,则当前节点node作为根节点
this.root = node;
this.size = 1;
return true;
}
TreeNode parent = null;
TreeNode cur = this.root;
//parent始终指向cur的父节点,和链表插入类似,也需要记录指定位置的前一个结点
while (cur != null) {
if (key == cur.key) {
return false;//key重复了
} else if (key < cur.key) {
//如果要找到的结点小于当前节点,就去左子树寻找
parent = cur;
cur = cur.left;
} else {
//key>cur.key
//如果要找的数大于当前节点,就去右子树找
parent = cur;
cur = cur.right;
}
}
//cur==null
//保证parent一定是cur的双亲
//断言parent!=null
//要做的工作,把node插入到parent的孩子中
if(key
二叉搜索树的删除操作需要考虑多种情况,首先要找到删除的数和父节点,考虑:
//删除操作
public boolean remove(long key){
TreeNode parent=null;
TreeNode cur=root;
//如果根节点为空,当前节点作为根
while(cur!=null){
//要删除的节点不为空,则去判断该节点是父节点还是叶子结点
if(key==cur.key){
deleteNode(parent,cur);
this.size--;
return true;
}else if(key 断言 toDeleteParent.right == toDelete
// else => 断言 toDeleteParent.left == toDelete
if (toDeleteParent.left == toDelete) {
toDeleteParent.left = toDelete.right;
} else {
// toDeleteParent.right == toDelete
toDeleteParent.right = toDelete.right;
}
}
}
分析二叉搜索树的时间复杂度,要知道它的最优情况和最坏情况分别是什么?
/*
若它的左子树不为空,则左子树上的所有结点都小于根结点上的值
若它的右子树不为空,则右子树上的所有结点都大于根结点上的值
它的左右子树也分别时搜索树
*/
/*
关于搜索树的类
验证该对象的合法性
1.size>=0
size和root之间的关系
2.size==通过遍历root得到的结点个数
3.root维护的树是搜索树,任取结点
中序遍历是有序的,key不重复——搜索树的规则
搜索树——>中序是有序的
中序是有序的——>搜索树
*/
public class BSTree {
private TreeNode root;
private int size;
public BSTree() {
this.root = null;
this.size = 0;
}
//查找操作
public boolean contains(long key) {
TreeNode cur = root;
while (cur != null) {//当前节点不为空
if (key == cur.key) {
return true;
} else if (key < cur.key) {
//如果要找的数小于当前节点值,就去左子树找
cur = cur.left;
} else {
//key>cur.key
//如果要找的数大于当前节点值,就去右子树找
cur = cur.right;
}
}
//如果整棵树遍历结束都找不到,则返回false
return false;
}
//插入操作
//如果key重复了,那么插入操作可能会失败
public boolean add(long key) {
//定义结点
TreeNode node = new TreeNode(key);
if (this.root == null) {
//如果根节点为空,则当前节点node作为根节点
this.root = node;
this.size = 1;
return true;
}
TreeNode parent = null;
TreeNode cur = this.root;
//parent始终指向cur的父节点,和链表插入类似,也需要记录指定位置的前一个结点
while (cur != null) {
if (key == cur.key) {
return false;//key重复了
} else if (key < cur.key) {
//如果要找到的结点小于当前节点,就去左子树寻找
parent = cur;
cur = cur.left;
} else {
//key>cur.key
//如果要找的数大于当前节点,就去右子树找
parent = cur;
cur = cur.right;
}
}
//cur==null
//保证parent一定是cur的双亲
//断言parent!=null
//要做的工作,把node插入到parent的孩子中
if(key 断言 toDeleteParent.right == toDelete
// else => 断言 toDeleteParent.left == toDelete
if (toDeleteParent.left == toDelete) {
toDeleteParent.left = toDelete.right;
} else {
// toDeleteParent.right == toDelete
toDeleteParent.right = toDelete.right;
}
}
}
public static void main(String[] args) {
BSTree tree = new BSTree();
long[] keys = { 5, 1, 6, 8, 3, 9, 0, 2, 4, 7 };
for (long key : keys) {
tree.add(key);
}
System.out.println(tree.remove(11));
}
}
以上就是今天二叉搜索树的相关内容,希望我们都能在二叉搜索树的代码练习中掌握有关知识!