码迷,mamicode.com
首页 > 其他好文 > 详细

二叉搜索树

时间:2018-09-10 17:59:38      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:inno   return   处理   规模   隔离   while   初始   cte   等于   

#ifndef BST_hpp
#define BST_hpp

#include "BinTree.hpp"
#include "Entry.hpp"
//二叉搜索树
//任何一个二叉树是二叉搜索树,当且仅当其中序遍历序列单调非降
template <typename T> class BST : public BinTree<T> {
protected:
    BinNodePosi(T) _hot; //"命中"节点的父亲
    BinNodePosi(T) connect34(  //按照"3+4"的结构,连接3个节点及3颗子树
                             BinNodePosi(T),BinNodePosi(T),BinNodePosi(T),
                             BinNodePosi(T),BinNodePosi(T),BinNodePosi(T),BinNodePosi(T));
    BinNodePosi(T) rotateAt(BinNodePosi(T) x); //对x及其父亲、祖父做统一旋转调整
    
public:
    virtual BinNodePosi(T)& search(const T& e); //查找
    virtual BinNodePosi(T) insert(const T& e); //插入
    virtual bool remove(const T& e); //删除
};


#pragma mark - 查找
//在以v为根的(AVL、SPLAY、rbTree等)BST子树中查找关键码e
template <typename T>
static BinNodePosi(T)& searchIn(BinNodePosi(T) & v, const T& e,BinNodePosi(T) & hot) {
    if (!v || (e == v->data)) {
        return v;
    }
    //一般情况:先记下当前节点,然后再深入一层,递归查找
    hot = v;
    
    return searchIn((e < v->data)? v->lc:v->rc, e, hot);
}

//searchIn的迭代版
#define EQUAL(e, v) (!(v) || (e) == (v)->data) //节点v(或假想的通配哨兵)的关键码等于e

template <typename T>
static BinNodePosi(T)& searchIn_I2(BinNodePosi(T) & v, const T& e,BinNodePosi(T) & hot) {
    if (EQUAL(e, v)) {
        return v;    //退化情况:在子树根节点v处命中
    }
    
    hot = v;
    
    while (1) {
        //确定深入方向
        BinNodePosi(T) & c = ( e < hot->data) ? hot->lc : hot->rc;
        
        if (EQUAL(e, c)) {
            return c;
        }
        
        hot = c;
    }//hot始终指向最后一个失败节点
    
}//返回时,返回值指向命中节点(或假想的通配哨兵),hot指向其父亲(退化时为初始值NULL)


template <typename T> BinNodePosi(T) & BST<T>::search(const T &e) {
    return searchIn(this->_root, e, _hot = NULL);
}

#pragma mark - 插入
//将关键码e插入BST树中
template <typename T> BinNodePosi(T) BST<T>::insert(const T &e) {
    BinNodePosi(T) &x = search(e);
    if (x) {
        return x; //确认目标不存在(留意对_hot的设置)
    }
    
    x = new BinNode<T> (e, _hot);  //创建新节点x:以e为关键码,以_hot为父
    this -> _size++;  //更新全树规模
    this -> updateHeightAbove(x);  //更新x及其历代祖先的高度
    return x;   //新插入的节点,必为叶子
}//无论e是否存在于原树中,返回时总有x->data == e

#pragma mark - 删除
template <typename T>
static BinNodePosi(T) removeAt(BinNodePosi(T) &x,BinNodePosi(T) &hot) {
    BinNodePosi(T) w = x;        //实际被摘除的节点,初值同x
    BinNodePosi(T) succ = NULL;  //实际被删除节点的接替者
    
    if ( ! HasLChild(*x) ){
        //若*x的左子树为空,则可直接将*x替换为其右子树
        succ = x = x -> rc;
    }else if ( !HasRChild(*x) ) {
        //若右子树为空,则可对称的处理---注意,此时succ != NULL
        succ = x = x -> lc;
    }else{
        //若左右子树均存在,则选择x的直接后继作为实际被摘除节点,为此需要(在右子树中)找到*x的直接后继*w
        //交换*x和*w的数据元素
        w = w -> succ();
        std::swap(x->data, w->data);
        BinNodePosi(T) u = w -> parent;
        ( (u == x) ? u->rc : u->lc ) = succ = w -> rc;  //隔离节点*w
    }
    
    
    hot = w -> parent; //记录实际被删除节点的父亲
    if (succ) {
        succ -> parent = hot;   //并将被删除节点的接替者与hot相连
    }
    
    delete w -> data;
    delete w;
    
    return succ;//释放被摘除节点,返回接替者
}

//从BST树中删除关键码e
template <typename T> bool BST<T>::remove(const T &e) {
    BinNodePosi(T) &x = search(e);
    if (!x) {   //确认目标存在(留意_hot的设置)
        return false;
    }
    
    removeAt(x, _hot);   //实施删除
    this -> _size--;
    this -> updateHeightAbove(_hot); //更新_hot及其历代祖先的高度
    return true;
}//删除成功与否,由返回值指示


template <typename T> BinNodePosi(T) BST<T>::connect34(BinNodePosi(T) a, BinNodePosi(T) b, BinNodePosi(T)c, BinNodePosi(T) T0, BinNodePosi(T) T1, BinNodePosi(T) T2, BinNodePosi(T) T3) {
    a -> lc = T0;
    if (T0) {
        T0 -> parent = a;
    }
    
    a -> rc = T1;
    if (T1) {
        T1 -> parent = a;
    }
    this -> updateHeight(a);
    
    
    c -> lc = T2;
    if (T2) {
        T2 -> parent = c;
    }
    
    c -> rc = T3;
    if (T3) {
        T3 -> parent = c;
    }
    this -> updateHeight(c);
    
    b -> lc = a;
    a -> parent = b;
    b -> rc = c;
    c -> parent = b;
    this -> updateHeight(b);
    return b;  //该子树新的根节点
}

//v为非空孙辈节点
template <typename T> BinNodePosi(T) BST<T>::rotateAt(BinNodePosi(T) v){
    
    BinNodePosi(T) p = v -> parent;
    BinNodePosi(T) g = p -> parent;
    
    if (IsLChild(*p)) { //zig
        
        if (IsLChild(*v)) { //zig--zig
            p -> parent = g -> parent;//向上联接
            return connect34(v, p, g, v->lc, v->rc, p->rc, g->rc);
        }else{  //zig--zag
            v -> parent = g -> parent;  //向上联接
            return connect34(p, v, g, p->lc, v->lc, v->rc, g->rc);
        }
        
    }else{ //zag
        
        if (IsRChild(*v)) { //zag--zag
            p -> parent = g -> parent;//向上联接
            return connect34(g, p, v, g->lc, p->lc, v->lc, v->rc);
        }else{ //zag---zig
            v -> parent = g -> parent; //向上联接
            return connect34(g, v, p, g->lc, v->lc, v->rc, p->rc);
        }
        
        
    }
    
}

#endif /* BST_hpp */

 

二叉搜索树

标签:inno   return   处理   规模   隔离   while   初始   cte   等于   

原文地址:https://www.cnblogs.com/gkp307/p/9621076.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!