zoukankan      html  css  js  c++  java
  • 二叉搜索树(BST)

    如图所示为一颗二叉搜索树,二叉搜索树是具有下列性质的二叉树或空树:

    1. 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

    2. 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

    3. 任意节点的左、右子树也分别为二叉查找树。

    4. 没有键值相等的节点。

    补充:二叉搜索树的中序遍历是有序的。

    二叉搜索树结构

    struct BSTnode{
        BSTnode *l,*r;//分别指向左右节点
        int val;//节点代表的值
        BSTnode(int v){//构造函数 
            l=r=NULL,val=v;
        }
    };

    二叉搜索树查找

    对于遇到的每个结点x,都会比较x.val与k的大小,如果相等,就终止查找,否则,决定是继续往左子树还是右子树查找。因此,整个查找过程就是从根节点开始一直向下的一条路径,若假设树的高度是h,那么查找过程的时间复杂度就是O(h)。
    BST查找代码如下

    BSTnode* search(int k){//二叉搜索树查找
        BSTnode* x=root;
        while(x!=NULL&&x->val!=k){
            if(x->val<k)x=x->r;
            else x=x->l;
        }
        return x;
    }

    二叉搜索树插入

    BST的插入过程非常简单,很类似与二叉树搜索树的查找过程。当需要插入一个新结点时,从根节点开始向下移动,直到遇到一个空的指针NIL,需要插入的值即被存储在该结点位置,如果已经存在,则直接退出。

    void insert(int k){//二叉搜索树插入 
        BSTnode *x=root,*y;
        while(x!=NULL&&x->val!=k){
            y=x;
            if(x->val<k)x=x->r;
            else x=x->l;
        }
        if(x!=NULL)return;//如果存在就直接退出 
        if(k<y->val)y->l=new BSTnode(k);
        else  y->r=new BSTnode(k);
    }

    二叉搜索树删除 

    二叉搜索树的结点删除比插入较为复杂,总体来说,结点的删除可归结为三种情况:
    1、 如果结点x没有孩子节点,那么只需简单地将其删除,并修改父节点,用NULL来替换x;
    2、 如果结点x只有一个孩子,那么将这个孩子节点提升到x的位置,并修改x的父节点,用x的孩子替换x;
    3、 如果结点x有2个孩子,那么找到子树中大于或小于k的最接近的值y,然后让y替换z。

    void remove(int k){//二叉搜索树删除 
        BSTnode *x=root,*y,*z;
        while(x!=NULL&&x->val!=k){
            y=x;
            if(x->val<k)x=x->r;
            else x=x->l;
        }
        if(x==NULL)return;//x不存在 
        if(x->l==NULL&&x->r==NULL){//x无子节点 
            if(k<y->val)delete x,y->l=NULL;
            else delete x,y->r=NULL;
            return;
        }
        if(x->l==NULL||x->r==NULL){//x只有一个子节点,用子节点替换x,二叉搜索树依然成立 
            if(x->l!=NULL){
                if(k < y->val){
                    y->l=x->l,delete x;
                }
                else y->r=x->l,delete x;
            }
            else{
                if(k < y->val){
                    y->l=x->r,delete x;
                }
                else y->r=x->r,delete x;
            }
            return ;
        }//x有两个子节点,则找到子树中大于或小于k的最接近的值替换
        z=x;
        y=x->r;while(y->l!=NULL)z=y,y=y->l;//用大于k的最接近的值替换 
        if(y->val>z->val)z->r=NULL;//一定要判断,不能认为y是z的左节点,因为z可以是x; 
        else z->l=NULL;
        x->val=y->val,delete y;
    }

    中序遍历(有序输出)

    void mid_traversal(BSTnode* x){//中序遍历,有序输出 
        if(x==NULL)return;
        mid_traversal(x->l);
        printf("%d ",x->val);
        mid_traversal(x->r);
    } 
  • 相关阅读:
    2018年-2019年第二学期第七周C#学习个人总结
    2018年-2019年第二学期第六周C#学习个人总结
    2018年-2019年第二学期第五周C#学习个人总结
    2018年-2019年第二学期第四周C#学习个人总结
    2018年-2019年第二学期第三周C#学习个人总结
    2018年-2019年第二学期第二周C#学习个人总结
    本学期C#学习个人总结
    排球积分程序
    观后感
    最终总结
  • 原文地址:https://www.cnblogs.com/bennettz/p/7604241.html
Copyright © 2011-2022 走看看