查找算法(一):二叉查找树BST

最近看Java集合类,底层很多关于高效查找的一些结构,比如哈希,红黑树等,也是有些遗忘了,所以正好系统总结一下查找相关的结构算法

查找表:同一种类型的数据元素构成的集合
查找:分为静态查找(只是查)和动态查找(还包括了插入元素和删除元素)——静态查找:顺序查找(遍历),折半查找,索引都比较简单,主要分析分析动态查找吧

动态查找

树结构

二叉查找树

二叉查找树(BST)是空树或者是满足下面要求的二叉树:
1.如果左子树不为空,那么左子树上任意节点的关键字的值都小于根节点关键字的值
2.如果右子树不为空,那么右子树上任意节点的关键字的值都大于根节点关键字的值
3.它的左右子树又分别是一个二叉查找树
性质

  • BST的中序遍历是一个递增的有序数列(构造树的过程就相当于排序的过程)
  • 每次插入元素的时候不需要移动其他的结点,都是在添加新的叶子结点,改变指针即可

用Java实现一下基本操作
定义一个BST树结构如下:

public class BTreeNode {
        int val;//节点的关键字值
        BTreeNode left;//左子树
        BTreeNode right;//右子树
        BTreeNode(int x) { val = x; }
    }

查找算法实现

//找到目标值返回该值对应的树节点,找不到返回null
    public BTreeNode searchBST(BTreeNode node,int des){
        if(node == null)
            return null;
        if(node.val == des)
            return node;
        if(des > node.val)
            return searchBST(node.right,des);
        else
            return searchBST(node.left,des);
    }

查找的时间复杂度分析:复杂度和BST的树结构有很大的关系,如果全部的节点都是按照关键字递增或者递减的顺序插入来构造的,那么构造的二叉树就会退化成单链结构,成了线性复杂度O(n)了,最好的情况就是节点都最大程度上靠近根节点,这样平均和最好情况的查找时间都是O(logn)了,也就是树高。

插入算法描述

//返回插入元素之后的新的树结构
    public BTreeNode insertBST(BTreeNode node,int des){
        if(node == null)//如果根节点为空,那么新建一个树返回
            return new BTreeNode(des);
        if(des == node.val)//如果跟根节点的键值等于插入值,那么查找成功,返回原先的树即可
            return node;
        if(des > node.val)//递归调用插入
            node.right = insertBST(node.right,des);
        else
            node.left = insertBST(node.left,des);
        return node;
    }

基本还是基于查找算法的,对于找到的元素那么就不用插入了,直接返回原先的树即可;如果插入值大于节点的关键字值,那么问题转换为在节点的右子树中插入值为关键字的节点,小于时的情况类似,最后记得return即可

删除算法描述

在BST中删除某个关键字的节点,要保证删除之后整个树结构还保持有序的特性,删除的情况有一下三种:

  • 如果关键字值对应的节点是叶子节点,那么直接改变它的双亲节点的指向即可
  • 如果关键字值对应的节点只含有右子树或者左子树,那么直接将右子树或者左子树的根节点连接到原先的双亲节点即可
  • 如果删除的结点左右子树都存在,那么就存在一个选取新的连接结点的问题:选组的结点对应的关键字值一定要大于被删除结点原先左子树中所有结点的关键字并且小于被删除结点原先右子树中所有结点的关键字——也就是被删除结点左子树中最右结点或者被删结点的右子树的最左结点
public BTreeNode removeBST(BTreeNode node,int des){
        if(node == null)
            return null;
        if(des == node.val){//查找成功,开始删除
            if(node.left == null && node.right == null)
                return null;//左右子树都是空的,直接返回null
            if(node.left == null && node.right != null)
                return node.right;//左子树为空的时候,右子树顶点就是新的头了
            if(node.left != null && node.right == null)
                return node.left;//右子树为空的时候,左子树顶点就是新的头了
            else{//两个子树都不为空
                BTreeNode tmp = node.left;
                while(tmp.right != null){
                    tmp = tmp.right;//找到左子树的最右结点
                }
                node.val = tmp.val;//直接替换值
                node.left = removeBST(node.left,tmp.val);//将左子树的最有结点删除
            }
        }
        else if(des > node.val)
            node.right =  removeBST(node.right,des);
        else
            node.left =  removeBST(node.left,des);
        return node;
    }

实现时注意递归结束条件,这样在删除的元素不存在的时候,就会返回一个原先的树结构

发布了9 篇原创文章 · 获赞 1 · 访问量 179

猜你喜欢

转载自blog.csdn.net/PanicJaw/article/details/105126872
今日推荐