二叉搜索树的基本操作

二叉搜索树的基本性质:节点的左子值小于等于节点的,右子值大于等于节点值,的二叉树。

二叉树的插入删除查找操作:

#include <iostream>
using namespace std;
class BinTreeNode{
public:
    BinTreeNode * p;
    BinTreeNode * left;
    BinTreeNode * right;
    int key;
    BinTreeNode(int key,BinTreeNode * p=NULL,
        BinTreeNode* left=NULL,BinTreeNode*right=NULL){
        this->key = key;
        this->p = p;
        this->left = left;
        this->right = right;
    }
};
class SearchTree{
public:
    SearchTree();
    ~SearchTree();
    void Insert(int x);
    BinTreeNode * Search(int x);
    void Empty(BinTreeNode * n);
    BinTreeNode * Minimum(BinTreeNode *n);
    BinTreeNode * Maximum(BinTreeNode *n);
    int Delete(BinTreeNode * n);
    void InorderTreeWalk(){
        InorderTreeWalk(root);
    }
    void PreTreeWalk(){
        PreTreeWalk(root);
    }
    void PostTreeWalk(){
        PostTreeWalk(root);
    }
    BinTreeNode * Root(){
        return root;
    }
    BinTreeNode * Successor(BinTreeNode * n);
    BinTreeNode * Predecessor(BinTreeNode * n);
private:
    void InorderTreeWalk(BinTreeNode * n);
    void PreTreeWalk(BinTreeNode * n);
    void PostTreeWalk(BinTreeNode * n);
    BinTreeNode * root;
};

SearchTree::SearchTree(){
    root = NULL;
}
/**
 * 析构函数 删除所有节点并释放内存
 */
SearchTree::~SearchTree(){
    Empty(root);
}
/**
 * 清空元素
 */
void SearchTree::Empty(BinTreeNode * n){
    if(n){
        Empty(n->left);
        Empty(n->right);
        delete n;
    }
}
/**
 * 插入一个元素
 */
void SearchTree::Insert(int x){
    if(NULL == root){
        root = new BinTreeNode(x);
    }else{
        BinTreeNode *t = root,*p = NULL;
        while(t){
            p = t;
            if(x<t->key)
                t = t->left;
            else
                t = t->right;
        }
        t = new BinTreeNode(x,p);
        if(x<p->key)
            p->left = t;
        else
            p->right = t;
    }
}
/**
 * 查找指定节点子树中最小值节点
 */
BinTreeNode * SearchTree::Minimum(BinTreeNode * n){
    /**
     * 子树中最小的节点应该在根的左最小子孙节点,因为左边始终比右边小
     */
    while(n->left)
        n = n->left;
    return n;
}
/**
 * 查找指定节点子树中最大的节点
 */
BinTreeNode * SearchTree::Maximum(BinTreeNode * n){
    while(n->right)
        n = n->right;
    return n;
}
/**
 * 中序遍历
 */
void SearchTree::InorderTreeWalk(BinTreeNode * n){
    if(n){
        InorderTreeWalk(n->left);
        cout<<n->key<<" ";
//      cout<<n->key<<"后驱"<<(Successor(n) ? Successor(n)->key : -1)
        <<"前驱"<<(Predecessor(n) ? Predecessor(n)->key : -1)<<endl;
        InorderTreeWalk(n->right);
    }
}
/**
 * 前序遍历
 */
void SearchTree::PreTreeWalk(BinTreeNode * n){
    if(n){
        cout<<n->key<<" ";
        PreTreeWalk(n->left);
        PreTreeWalk(n->right);
    }
}
/**
 * 后序遍历
 */
void SearchTree::PostTreeWalk(BinTreeNode * n){
    if(n){
        PostTreeWalk(n->left);
        PostTreeWalk(n->right);
        cout<<n->key<<" ";
    }
}
/**
 * 查找一个节点的后继
 */
BinTreeNode * SearchTree::Successor(BinTreeNode * n){
    /**
     * 如果有右孩子 那么是右子树中最小者
     */
    if(n->right){
        return Minimum(n->right);
    }else{
        /**
         * 如果无右孩子,所求节点为左节点仍是x祖先的节点 且是最近的
         * 算法:记录当前节点与父节点 如果父节点的左节点是当前节点
         * 那么就是父节点
         */
        while(n->p){
            if(n->p->left == n)
                break;
            else
                n = n->p;
        }
        return n->p;
    }
}
/**
 * 查找一个节点的前区
 */
BinTreeNode * SearchTree::Predecessor(BinTreeNode * n){
    /**
     * 如果有左孩子 就是左子树中最大的节点
     */
    if(n->left){
        return Maximum(n->left);
    }else{
    /**
     * 如果没有左子树 所求节点为右节点仍然是x的祖先的节点
     * 算法:类比上面
     */
        while(n->p){
            if(n->p->right == n)
                break;
            else
                n = n->p;
        }
        return n->p;
    }
}
int SearchTree::Delete(BinTreeNode * n){
    /**
     * 如果节点没有孩子 直接将父节点指向该节点的指针置为空即可
     * 如果有一个孩子 那么将父节点指向子节点即可
     * 如果有两个孩子 那么找到后继 因为x有右子,
     * 那么后继在右树中最小没有左孩子
     * 删除后继 然后用后继的数据代替x即可
     */
    BinTreeNode * y,*x;
    if(!n->left || !n->right)//有一个孩子 或 无孩子
        y = n;
    else//n有两个孩子 但y只有右孩子
        y = Successor(n);
    if(y->left != NULL)//有左孩子 无右孩子
        x = y->left;
    else//有右孩子或者无
        x = y->right;
    //y代表待删除节点 x代表待删除节点的子节点,因为无论n有几个孩子
    //待删除元素最多只有一个孩子
    //先将父节点指针链接上 然后是左右节点指针
    if(x!=NULL)
        x->p = y->p;
    if(y->p == NULL)
        root = x;
    else
        if(y== y->p->left)
            y->p->left = x;
        else
            y->p->right = x;
    if(y != n)
        n->key = y->key;
    int key = y->key;
    delete y;
    return key;
}
int main(void){
    SearchTree st;
    st.Insert(6);
    st.Insert(2);
    st.Insert(8);
    st.Insert(5);
    st.Insert(9);
    st.Insert(7);
    st.InorderTreeWalk();
    cout<<endl;
    st.Delete(st.Root()->right);
    st.InorderTreeWalk();
    cout<<endl;
    st.Delete(st.Root()->right);
    st.InorderTreeWalk();
    cout<<endl;
    st.Delete(st.Root()->right);
    st.InorderTreeWalk();
    cout<<endl;
    return 0;
}

二叉搜索树的插入搜索删除取决于树的高度,其时间复杂度为 O(logn)