二叉搜索树(BST)
BST:或者是一棵空树,
或者对于任何一个结点,设其值为K,则该结点的左子树的值小于K,右结点的值大于K。
二叉搜索树按照中根遍历将各个结点打印,将得到按照大到小的顺序排列。
BSG示意图:
二叉搜索树的效率在于检索,将算法复杂度从2^k减少到log(n)
检索方式:
从根结点开始,如果等于根结点值直接返回,如果大于根节点从右子树开始继续检索,
如果小于根结点从左子树继续检索,重复这一过程,直到找到对应结点或者返回空。
插入:类似于检索方式。
BST的创建:
1)非递归算法,构建二叉树
public void insert(T data) {
//插入数据为空 直接返回
if (data == null){
return;
}
//根几点为空,初始化根结点,返回
if (root == null){
root = new BinaryNode<>(data);
return;
}
BinaryNode<T> current = root;
//插入之和根几点比较
int rst = data.compareTo(current.getData());
while (true){
//相等的结点无需插入
if (rst == 0){
return;
}
//大于根结点,继续往右
if (rst == 1){
//右结点为空插入
if (current.getRight() == null){
current.setRight(new BinaryNode<>(data));
return;
}else {
current = current.getRight();
}
//小于根结点,继续往左
}else {
//左结点为空插入
if (current.getLeft() == null){
current.setLeft(new BinaryNode<>(data));
return;
}else {
current = current.getLeft();
}
}
rst = data.compareTo(current.getData());
}
}
2)非递归算法,检索
public BinaryNode findNode(T data) {
//查找值为空,返回
if (data == null){
return null;
}
//root为空返回
BinaryNode<T> current = root;
if (current == null){
return null;
}
//当前值和根结点比较
int rst = data.compareTo(current.getData());
while (true){
//相等,返回
if (rst == 0){
return current;
}
//当前值比根结点大,继续往右
if (rst == 1){
//根结点右子结点为空,当前值不在树中,返回空
if (current.getRight() == null){
return null;
}else {
current = current.getRight();
}
//当前值比根结点
}else {
if (current.getLeft() == null){
return null;
}else {
current = current.getLeft();
}
}
rst = data.compareTo(current.getData());
}
}
搜索二叉树删除:
从二叉搜索树删除结点,不能把这个结点为根的子树都删掉,只能删除这个结点,
并还要保持二叉搜索树的原来的特性。
设要删除结点为K,若K不存在左子树,直接用右子树替代当前结点。
K(parent)->right = K->right
若K存在左子树,找到左子树中值最大结点,用最大结点替换删除结点,
设找到的最大结点为G,
若G不存在左子树且G的parent不是K,用G替换K,
G->left = K->left;
G->right = k->right;
G(parent)-> = null;
K(parent) ->(left/right) = G;
若G存在左子树且G的parent不是K,用G替换K,
G(parent)->right = G->left;
G->left = K->left;
G->right = k->right;
K(parent) ->(left/right) = G;
若G的parent为K,用G替换K,
G->right = K->right
K(parent)->(left/right) = G
删除代码如下:
public void remove(T data) {
//树为空,删除值为空,返回
if (data == null || root == null){
return;
}
//查找删除结点的父结点
BinaryNode<T> parent = findParent(root,data);
//判断是根节点或者是左右子树
int tag ;
BinaryNode<T> delPoint ;
//父结点为空,表示是树根,并判断删除结点为根节点的左子节点还是右结点
if (parent == null){
tag = 0;
delPoint = root;
}else if (parent.getLeft() !=null && data.compareTo(parent.getLeft().getData()) == 0){
//左子树
tag = 1;
delPoint = parent.getLeft();
}else {
//右子树
tag = 2;
delPoint = parent.getRight();
}
BinaryNode<T> tmpParent = null;
//替换结点
BinaryNode<T> tmp = delPoint.getLeft();
//左子结点不为空
if (tmp != null){
while (tmp.getRight() != null){
tmpParent = tmp;
tmp = tmp.getRight();
}
if (tmpParent == null){
//左子树无右子树
delPoint.setLeft(tmp.getLeft());
}else {
//左子树有右子树
tmpParent.setRight(tmp.getLeft());
}
tmp.setLeft(delPoint.getLeft());
tmp.setRight(delPoint.getRight());
//左子结点为空,
}else {
tmp = delPoint.getRight();
}
if (tag == 0){
root = tmp;
}else if (tag == 1){
parent.setLeft(tmp);
}else parent.setRight(tmp);
}
private BinaryNode<T> findParent(BinaryNode<T> node,T data){
BinaryNode<T> tmpParent = null;
BinaryNode<T> tmp = node;
int rst = data.compareTo(tmp.getData());
while (true){
if (rst == 0){
return tmpParent;
}
if (rst == 1){
if (tmp.getRight() == null){
throw new UnsupportedOperationException("no such element");
}else {
tmpParent = tmp;
tmp = tmp.getRight();
}
}else {
if (tmp.getLeft() == null){
throw new UnsupportedOperationException("no such element");
}else {
tmpParent = node;
tmp = tmp.getLeft();
}
}
rst = data.compareTo(tmp.getData());
}
}
搜索二叉树总结:
搜索二叉实现了对数据的快速查找,降低算法复杂度。
搜索二叉树的难点,创建和删除