简述数据结构:二叉查找树

二叉查找树的性质

当一棵二叉树满足下面条件的时候就成了二叉查找树:对于树的任意一个节点,左儿子的值比右儿子小(或者反过来也行)。
二叉查找树本质还是二叉树,因此也具有二叉树的性质。

二叉查找树的操作

1. 判断某元素是否在树中:contains

这个操作比较简单,递归查找树根.

//公有函数contains通过调用私有函数contains递归查找。
bool contains(const Object &e) const
{
    return contains(e, root);
}

bool contains(const Object &e, Node *t)
{
    if(t == NULL)
        return false;

    if(e < t->element)
        return contains(e, t->left);
    else if(t->element < e)
        return contains(e, t->right);
    else
        return true;
}

2. 插入一个元素:insert

往一个二叉查找树中插入元素不会改变原树的结构,只需要找到一个合适的位置满足二叉查找树的性质就可以了。

void insert(const Object &e)
{
    insert(e, root);
}
//私有函数操作子树,二叉查找树的插入操作不会改变原树的结构
void insert(const Object &e, Node *&t)
{
    //空子树
    if(t == NULL)
    {
        t = new Node(e,NULL,NULL);
    }
    else
    {
        if(e < t->element)
            insert(e, t->left);
        else if(t->element < e)
            insert(e, t->right);
        else
            ;
    }
}

3. 删除一个元素:remove

删除一个元素必须分情况来讨论。

  1. 要删除的节点是叶子。
    如果要删除的节点是一个叶子,那么只需要简单地删除这个节点,并将其父节点的相关指针置为NULL就可以了,具体的做法是直接将这个节点的指针变为NULL,然后释放其存储。
  2. 要删除的节点只有一个子树。
    如果要删除的节点只有一个子树,那么只需要让该节点的父节点指向节点的子树,然后释放掉该节点的存储。
  3. 要删除的节点有两个子树。
    如果要删除的节点有两个子树,那么需要找出该节点右子树中的最小元素,并将这个最小元素赋给本节点,再将右子树中的该元素删除,此时的删除操作就转化成了1中情况(最小元素必为叶子)。

其中,上述1和2可以合并实现。

void remove(const Object &e)
{
    remove(e, root);
}
void remove(const Object &e, Node *&t)
{
    if(t == NULL)
        return;

    //未找到元素e,于是递归查找
    if(e < t->element)
        remove(e, t->left);
    else if(t->element < e)
        remove(e, t->right);
    //找到元素e
    else if(t->left != NULL && t->right != NULL) //有两个子节点
    {
        t->element = findMin(t->right);
        remove(t->element, t->right);
    }
    else
    {
        Node *old = t;
        t = (t->left != NULL)? t->left : t->right;
        delete old;
    }
}

二叉查找树C++实现

template <typename Object>
class BinarySearchTree
{
    public:
        BinarySearchTree():root(NULL){}
        BinarySearchTree(BinarySearchTree &t)
        {
            root = t;  //浅拷贝
        }
        ~BinarySearchTree()
        {
            makeEmpty();
        }
    
        //深拷贝
        BinarySearchTree & operator =(BinarySearchTree &t)
        {
            if(root == t)
                return;
            if(root != NULL)
                makeEmpty();
            root = clone(root);
        }

        void insert(const Object &e)
        {
            insert(e, root);
        }
        void remove(const Object &e)
        {
            remove(e, root);
        }
        bool contains(const Object &e) const
        {
            return contains(e, root);
        }
        bool isEmpty() const
        {
            return root == NULL;
        }

        const Object & findMin() const
        {
            return findMin(root);
        }
        const Object & findMax() const
        {
            return findMax(root);
        }

        void makeEmpty()
        {
            makeEmpty(root);
        }

        void printTree()
        {
            printTree(root);
            std::cout<<"--------------"<<std::endl;
        }
    private:
        struct Node
        {

            Object element;
            Node *left;
            Node *right;
            Node(const Object &ele, Node *l, Node *r):element(ele),left(l),right(r){}
        };

        Node *root;
        
        //私有函数操作子树,二叉查找树的插入操作不会改变原树的结构
        void insert(const Object &e, Node *&t)
        {
            //空子树
            if(t == NULL)
            {
                t = new Node(e,NULL,NULL);
            }
            else
            {
                if(e < t->element)
                    insert(e, t->left);
                else if(t->element < e)
                    insert(e, t->right);
                else
                    ;
            }
        }

        void remove(const Object &e, Node *&t)
        {
            if(t == NULL)
                return;

            //未找到元素e,于是递归查找
            if(e < t->element)
                remove(e, t->left);
            else if(t->element < e)
                remove(e, t->right);
            //找到元素e
            else if(t->left != NULL && t->right != NULL) //有两个子节点
            {
                t->element = findMin(t->right);
                remove(t->element, t->right);
            }
            else
            {
                Node *old = t;
                t = (t->left != NULL)? t->left : t->right;
                delete old;
            }
            

        }

        bool contains(const Object &e, Node *t)
        {
            if(t == NULL)
                return false;

            if(e < t->element)
                return contains(e, t->left);
            else if(t->element < e)
                return contains(e, t->right);
            else
                return true;

        }

        const Object & findMin(Node *t) const
        {
            while(t->left != NULL)
            {
                t = t->left;       //查找最左边的元素
            }

            return t->element;
        }
    
        const Object & findMax(Node *t) const
        {
            while(t->right != NULL)
            {
                t = t->right;     //查找最右边的元素
            }

            return t->element;
        }

        void makeEmpty(Node * &t)
        {
            if(t != NULL)
            {
                makeEmpty(t->left);
                makeEmpty(t->right);
                delete t;
            }
             t = NULL;
        }

        Node * clone(Node *t)
        {
            if(t == NULL)
                return;
            
            return new Node(t->element, t->left, t->right); 

        }

        void printTree(const Node *t)
        {
            if(t == NULL)
                return;
            std::cout<<t->element<<std::endl;
            if(t->left != NULL)
                printTree(t->left);
            if(t->right != NULL)
                printTree(t->right);
        }
};
    原文作者:野风鼓瑟震山岗
    原文地址: https://www.cnblogs.com/jaletech/p/3903347.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞