您的位置:首页 > 编程语言 > C语言/C++

【C++】实现的二叉搜索树BST

2016-07-07 22:30 567 查看

概念:

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树),二叉搜索树是一种特殊的二叉树

二叉搜索树的性质:

1. 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同。
2. 左子树上所有节点的关键码(key)都小于根节点的关键码(key)。
3. 右子树上所有节点的关键码(key)都大于根节点的关键码(key)。
4. 左右子树都是二叉搜索树。

根据二叉搜索树的性质知:对二叉搜索树进行中序遍历得到的结点序列必然是一个有序序列。

接下来用C++代码实现搜索二叉树,若有错误或不足之处,还望各位大神指点。。。

代码:(代码中间包含了对基本功能(插入,删除,查找)的递归和非递归的实现)

[cpp] view
plain copy

 





<span style="font-size:18px;">include <iostream>  

#include <string>  

using namespace std;  

  

template<class K,class V>  

struct BSTreeNode  

{  

    K _data;            //值  

    V _freq;                //出现的频率  

  

    BSTreeNode<K, V>* _left;      //指向左子树的指针  

    BSTreeNode<K, V>* _right;     //指向右子树的指针  

  

    BSTreeNode(const K& data, const V& freq)//初始化  

        :_data(data)  

        , _freq(freq)  

        , _left(NULL)  

        , _right(NULL)  

    {}  

};  

template<class K, class V>  

struct BSTree  

{  

    typedef BSTreeNode<K, V> Node;  

public:  

    BSTree()//初始化  

        :_root(NULL)  

    {}  

    //插入  

    bool Insert(const K& data, const V& freq)  

    {  

        if (_root == NULL)//如果节点为空,就在此节点处加入data数据  

        {  

            _root = new Node(data, freq);  

            return true;  

        }  

  

        Node* parent = NULL;  

        Node* cur = _root;  

        while (cur)//搜索data应该插入的节点:parent节点后  

        {  

            if (data > cur->_data)//如果data大于节点的值,就继续在节点的右子树中插入data  

            {  

                parent = cur;  

                cur = cur->_right;  

            }  

            else if (data < cur->_data)//如果data小于节点的值,就继续在节点的左子树中插入data  

            {  

                parent = cur;  

                cur = cur->_left;  

            }  

            else  

            {  

                cur->_freq++;  

                return true;  

            }  

        }  

        //在parent节点后插入data  

        if (data > parent->_data)  

        {  

            parent->_right = new Node(data, freq);  

        }  

        else  

        {  

            parent->_left = new Node(data, freq);  

        }  

        return true;  

    }  

    Node* Find(const K& data)//查找  

    {  

        Node* cur = _root;  

        while (cur)  

        {  

            if (data >cur->_data)//若data大于当前节点,则在当前节点的右子树中查找  

            {  

                cur = cur->_right;  

            }  

            else if (data < cur->_data)//若data小于当前节点,则在当前节点的左子树中查找  

            {  

                cur = cur->_left;  

            }  

            else  

            {  

                return cur;  

            }  

        }  

        return NULL;  

    }  

    bool Remove(const K& data)//删除  

    {  

        Node* parent = NULL;  

        Node* cur = _root;  

  

        while (cur)//寻找data节点cur  

        {  

            if (data > cur->_data)  

            {  

                parent = cur;  

                cur = cur->_right;  

            }  

            else if (data < cur->_data)  

            {  

                parent = cur;  

                cur = cur->_left;  

            }  

            else//要么cur==NULL退出了循环,要么data==cur->_databreak  

            {  

                break;  

            }  

        }  

  

        if (cur == NULL)  

        {  

            return false;  

        }  

  

        //1.左为空,或者右为空  

        //2.左右都不为空  

        if (cur->_left == NULL)  

        {//cur的左为空  

            if (parent == NULL)//删除的是根节点  

            {  

                _root = cur->_right;  

            }  

            else  

            {  

                if (parent->_left == cur)  

                {  

                    parent->_left = cur->_right;  

                }  

                else  

                {  

                    parent->_right = cur->_right;  

                }  

            }  

          

            delete cur;  

        }  

        else if (cur->_right == NULL)  

        {//cur的右为空  

            if (parent == NULL)  

            {  

                _root = cur->_right;  

            }  

            else  

            {  

                if (parent->_left == cur)  

                {  

                    parent->_left = cur->_left;  

                }  

                else  

                {  

                    parent->_right = cur->_left;  

                }  

            }  

            delete cur;  

        }  

        else  

        {//左不为空,右也不为空  

            parent = cur;  

            Node *subLeft = cur->_right;//subarea node  子区节点  

            while (subLeft->_left)  

            {//遍历删除节点的左子树??  

                parent = subLeft;  

                subLeft = subLeft->_left;  

            }  

            cur->_data = subLeft->_data;  

            cur->_freq = subLeft->_freq;  

  

            if (parent->_left == subLeft)  

            {  

                parent->_left = subLeft->_right;  

            }  

            else  

            {  

                parent->_right = subLeft->_right;  

            }  

            delete subLeft;  

        }  

        return true;  

    }  

  

    //以下是递归方式  

    bool InsertR(const K& data, const V& freq)  

    {  

        return _InsertR(_root, data, freq);  

    }  

    bool _InsertR(Node*& root, const K& data, const V& freq)  

    {  

        if (root == NULL)  

        {  

            root = new Node(key, freq);  

            return true;  

        }  

  

        if (data > root->_data)  

        {  

            return _InsertR(root->_right, key, freq);  

        }  

        else if (data < root->_data)  

        {  

            return _InsertR(root->_left, key, freq);  

        }  

        else  

        {  

            return false;  

        }  

    }  

    Node* FindR(const K& data)  

    {  

        return _FindR(_root, data);  

    }  

    Node* _FindR(Node*& root, const K& data)  

    {  

        if (root == NULL)  

        {  

            return NULL;  

        }  

  

        if (data > root->_data)  

        {  

            return _FindR(root->_right, key);  

        }  

        else if (data < root->_data)  

        {  

            return _FindR(root->_left, key);  

        }  

        else  

        {  

            return root;  

        }  

    }  

  

    bool RemoveR(const K& data)  

    {  

        return _RemoveR(_root, data);  

    }  

    bool _RemoveR(Node*& root, const K& data)  

    {  

        if (root == NULL)  

        {  

            return false;  

        }  

        if (data > root->_data)  

        {  

            return _RemoveR(root->_right, data);  

        }  

        else if (data < root->_data)  

        {  

            return _RemoveR(root->_left, data);  

        }  

        else  

        {  

            Node* del = root;  

            if (root->_left == NULL)  

            {  

                root = root->_right;  

            }  

            else if (root->_right == NULL)  

            {  

                root = root->_left;  

            }  

            else  

            {  

                Node* parent = root;  

                Node* subLeft = root->_right;  

                while (subLeft->_left)  

                {  

                    parent = subLeft;  

                    subLeft = subLeft->_left;  

                }  

                root->_data = subLeft->_data;  

                root->_freq = subLeft->_freq;  

  

                del = subLeft;  

  

                if (parent->_left == subLeft)  

                {  

                    parent->_left = subLeft->_right;  

                }  

                else  

                {  

                    parent->_right = subLeft->_right;  

                }  

            }  

            delete del;  

            return true;  

        }  

    }  

  

    void InOrder()  

    {  

        _InOrder(_root);  

        cout << endl;  

    }  

    void _InOrder(Node* root)  

    {  

        if (root == NULL)  

            return;  

  

        _InOrder(root->_left);  

        cout << root->_data << " ";  

        _InOrder(root->_right);  

    }  

protected:  

    Node* _root;  

};</span>  

在删除算法过程中要注意细节情况

1.删除根节点

2.删除叶子节点

3.删除带有子树的节点


算法分析:

它和二分查找一样,插入和查找的时间复杂度均为lgN,但是在最坏的情况下仍然会有N的时间复杂度。原因在于插入和删除元素的时候,树没有保持平衡。我们追求的是在最坏的情况下仍然有较好的时间复杂度,这就是后面要讲的平衡查找树的内容了。下文首先讲解平衡查找树的最简单的一种:2-3查找树。

BST与二分查找一样,插入与查找的时间复杂度均为lgN,但是BST最坏情况是插入一个本身的有序的数列,这样在构建BST时会退化成类似于数组结构

即:

有一篇BST分析的很到位,链接是:
http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html
所以也就衍生出AVL树即平衡二叉查找树
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息