搜索二叉树的实现

要模拟实现搜索二叉树,必须了解他的性质:
搜索二叉树的性质:
1,每个节点都有一个用于搜索的关键码,每个节点的关键码都不一样;
2,一个节点的左子树上所有的关键码总是小于它,而右子树的关键总是大于它;
3,每一个子树都是一个搜索二叉树;

这里简单来模拟实现一下搜索二叉树(递归和非递归):
插入:
当插入一个节点时,你会发现新插入节点不会影响原先树的结构,所以不用调整,这是简单之处。

    bool _Insert(const K& x)
    {
        if (_root == NULL)
        {
            _root = new Node(x);
        }
        else
        {
            Node* cur = _root;
            Node* parent = cur;
            while (cur)
            {
                if (cur->_key > x)
                {
                    parent = cur;
                    cur = cur->_left;
                }
                else if (cur->_key < x)
                {
                    parent = cur;
                    cur = cur->_right;
                }
                else
                {
                    return false;
                }
            }
            if (parent->_key > x)
            {
                parent->_left = new Node(x);
            }
            else
            {
                parent->_right = new Node(x);
            }
        }
        return true;
    }

删除:
先遍历搜索树找到删除节点,下面主要分三种情况:
1,删除节点无左子树;
2,删除节点无右子树;
3,左右子树都有。
这里写图片描述
对于1,2两种情况,如果该节点是根节点时,只需将他仅有的那个孩子的根节点设为新的根节点即可,如果不是根节点,删除这个节点,还需将父节点与他的子树连接在一起,这种情况下,你就得判断自己是父节点的左孩子还是右孩子。而对于3这种情况,你需找一个新的节点来替代它,这里删这个节点不是真的删他自己,而是删了一个替代节点,替代节点有两个选择:左子树的最右节点(左子树最大值),右子树的最左节点(右子树最小值),找到替代节点,将他的关键码赋给待删除节点,然后删除它即可,但这里还有一个关键得注意(这里替代节点取右子树最左节点为例),这个最左节点的父节点可能是根节点,也可能不是,这里影响后面的连接。

    bool _Remove(const K& x)
    {
        if (_root == NULL)
            return false;
        Node* del = _root;
        Node* parent = del;
        while (del)
        {
            if (del->_key == x) //被删除的节点找到(左为空,右为空,左右均不为空)
            {
                Node* cur = del;
                if (cur->_left == NULL)   //删除节点无左子树
                {
                    if (cur == _root)
                        _root = _root->_right;
                    else
                    {
                        if (parent->_left == cur)
                            parent->_left = cur->_right;
                        else
                            parent->_right = cur->_right;
                    }
                }
                else if (cur->_right == NULL)   //删除节点无右子树
                {
                    if (cur == _root)
                        _root = _root->_left;
                    else
                    {
                        if (parent->_left == cur)
                            parent->_left = cur->_left;
                        else
                            parent->_right = cur->_left;
                    }
                }
                else  //左右子树都有
                {
                    cur = cur->_right;
                    while (cur->_left)
                    {
                        parent = cur;
                        cur = cur->_left;
                    }
                    del->_key = cur->_key;
                    del = cur;

                    if (cur == parent->_left)    //注意,此时的cur是最左节点
                        parent->_left = cur->_right;
                    else                         //此时的cur为根节点的右子树的根节点,parent为根节点
                        parent->_right = cur->_right;
                }
                delete del;
                del = NULL;

                return true;
            }
            else if (del->_key > x)
            {
                parent = del;
                del = del->_left;
            }
            else
            {
                parent = del;
                del = del->_right;
            }
        }
        return false;
    }

    bool  _RemoveR(const K& x, Node* & root)
    {
        if (root == NULL)
            return false;

        if (root->_key > x)
            _RemoveR(x, root->_left);
        else if (root->_key < x)
            _RemoveR(x, root->_right);
        else  //找到删除的位置
        {
            Node* del = root;
            if (root->_left == NULL)
            {
                root = root->_right;
            }
            else if (root->_right == NULL)
            {
                root = root->_left;
            }
            else
            {
                Node* parent = root->_right;
                Node* rootL = root->_right;
                while (rootL->_left)
                {
                    parent = rootL;
                    rootL = rootL->_left;
                }
                root->_key = rootL->_key;
                del = rootL;

                if (parent->_left == rootL)
                    parent->_left = rootL->_right;
                else
                    parent->_right = rootL->_right;
            }
            delete del;
            del = NULL;
            return true;

        }
    }

查找:

    Node* _Find(Node* root, const K& x)
    {
        while (root)
        {
            if (x > root->_key)
                root = root->_right;
            else if (x < root->_key)
                root = root->_left;
            else
                return root;
        }
        return NULL;
    }

Node* _FindR(Node* root, const K& x)
    {
        if (x > root->_key)
            return _FindR(root->_right, x);
        else if (x < root->_key)
            return _FindR(root->_left, x);
        else
        {
            return root;
        }
        return NULL;
    }

下面是完整代码:

#include<iostream>

using namespace std;

template<class K>
struct SearchBinaryTreeNode
{
    SearchBinaryTreeNode<K>* _left;
    SearchBinaryTreeNode<K>* _right;
    K _key;

    SearchBinaryTreeNode(const K& x)
        :_left(NULL),_right(NULL),_key(x)
    {}

};

template<class K>
class SearchBinaryTree
{
    typedef SearchBinaryTreeNode<K> Node;

public:
    SearchBinaryTree()
        :_root(NULL)
    {}

    ~SearchBinaryTree()
    {
        _Delete(_root);
    }
    void Insert(const K& x)
    {
        _Insert(x);
    }

    bool Remove(const K& x)
    {
        return _Remove(x);
    }

    void RemoveR(const K& x)
    {
        _RemoveR(x, _root);
    }

    Node* FindR(const K& x)
    {
        return _FindR(_root,x);
    }

    Node* Find(const K& x)
    {
        return _Find(_root,x);
    }
    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }

private:

    void _Delete(Node*& root)
    {
        if (root == NULL)
            return;
        _Delete(root->_left);
        _Delete(root->_right);
        delete root;
        root = NULL;
    }

    Node* _Find(Node* root, const K& x)
    {
        while (root)
        {
            if (x > root->_key)
                root = root->_right;
            else if (x < root->_key)
                root = root->_left;
            else
                return root;
        }
        return NULL;
    }

    Node* _FindR(Node* root, const K& x)
    {
        if (x > root->_key)
            return _FindR(root->_right, x);
        else if (x < root->_key)
            return _FindR(root->_left, x);
        else
        {
            return root;
        }
        return NULL;
    }



    void _InOrder(Node* root)
    {
        if (root)
        {
            _InOrder(root->_left);
            cout << root->_key << " ";
            _InOrder(root->_right);
        }
    }

    bool _Insert(const K& x)
    {
        if (_root == NULL)
        {
            _root = new Node(x);
        }
        else
        {
            Node* cur = _root;
            //Node* newNode = new Node(x);
            Node* parent = cur;
            while (cur)
            {
                if (cur->_key > x)
                {
                    parent = cur;
                    cur = cur->_left;
                }
                else if (cur->_key < x)
                {
                    parent = cur;
                    cur = cur->_right;
                }
                else
                {
                    return false;
                }
            }
            if (parent->_key > x)
            {
                parent->_left = new Node(x);
            }
            else
            {
                parent->_right = new Node(x);
            }
        }
        return true;
    }

    //删除一个数
    //1,叶子节点/左子树为空或右子树为空
    //2,左右子树均不为空
    bool _Remove(const K& x)
    {
        if (_root == NULL)
            return false;
        Node* del = _root;
        Node* parent = del;
        while (del)
        {
            if (del->_key == x) //被删除的节点找到(左为空,右为空,左右均不为空)
            {
                Node* cur = del;
                if (cur->_left == NULL)   //删除节点无左子树
                {
                    if (cur == _root)
                        _root = _root->_right;
                    else
                    {
                        if (parent->_left == cur)
                            parent->_left = cur->_right;
                        else
                            parent->_right = cur->_right;
                    }
                }
                else if (cur->_right == NULL)   //删除节点无右子树
                {
                    if (cur == _root)
                        _root = _root->_left;
                    else
                    {
                        if (parent->_left == cur)
                            parent->_left = cur->_left;
                        else
                            parent->_right = cur->_left;
                    }
                }
                else  //左右子树都有
                {
                    cur = cur->_right;
                    while (cur->_left)
                    {
                        parent = cur;
                        cur = cur->_left;
                    }
                    del->_key = cur->_key;
                    del = cur;

                    if (cur == parent->_left)    //注意,此时的cur是最左节点
                        parent->_left = cur->_right;
                    else                         //此时的cur为根节点的右子树的根节点,parent为根节点
                        parent->_right = cur->_right;
                }
                delete del;
                del = NULL;

                return true;
            }
            else if (del->_key > x)
            {
                parent = del;
                del = del->_left;
            }
            else
            {
                parent = del;
                del = del->_right;
            }
        }
        return false;
    }

    bool  _RemoveR(const K& x, Node* & root)
    {
        if (root == NULL)
            return false;

        if (root->_key > x)
            _RemoveR(x, root->_left);
        else if (root->_key < x)
            _RemoveR(x, root->_right);
        else  //找到删除的位置
        {
            Node* del = root;
            if (root->_left == NULL)
            {
                root = root->_right;
            }
            else if (root->_right == NULL)
            {
                root = root->_left;
            }
            else
            {
                Node* parent = root->_right;
                Node* rootL = root->_right;
                while (rootL->_left)
                {
                    parent = rootL;
                    rootL = rootL->_left;
                }
                root->_key = rootL->_key;
                del = rootL;

                if (parent->_left == rootL)
                    parent->_left = rootL->_right;
                else
                    parent->_right = rootL->_right;
            }
            delete del;
            del = NULL;
            return true;

        }
    }

    Node* _root;
};

下面是测试代码:

void Test()
{
    SearchBinaryTree<int> tree;
    tree.Insert(5);
    tree.Insert(1);
    tree.Insert(2);
    tree.Insert(3);
    tree.Insert(4);
    tree.Insert(9);
    tree.Insert(8);
    tree.Insert(6);
    tree.Insert(7);

    tree.RemoveR(5);
    tree.RemoveR(4);
    tree.RemoveR(1);
    tree.RemoveR(9);
    tree.RemoveR(2);
    tree.RemoveR(3);
    tree.RemoveR(6);
    tree.RemoveR(7);
    tree.RemoveR(8);
    //cout << tree.FindR(5) << endl;
    //cout << tree.Find(5) << endl;
    //cout << tree.Find(9) << endl;
    //cout << tree.Find(9) << endl;

    tree.~SearchBinaryTree();

    tree.InOrder();

}

int main()
{
    Test();
    system("pause");
    return 0;
}

分析

搜索二叉树的退化和缺陷:
这里写图片描述

搜索二叉树找一个数的运行效率取决于它的形状(N个节点),最好的情况是满二叉树,这时总共lgN层,时间复杂度是lgN,最差的情况是上图所示,总共N层。这时它的时间复杂度是N,这是因为这棵树已经不平衡了,对于最好的情况(满二叉树),可以参考二分查找。
对于上述问题,下篇文章会介绍到高度平衡的二叉搜索树,即 AVL树。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值