C++实现二叉搜索树基本操作(递归+非递归+应用)

基本概念不再多讲,看下面的例子

这里写图片描述

有如图的序列,用插入法建立二叉搜索树并完成相关操作:

代码:

#pragma once


#include <iostream>
#include <assert.h>
#include <string>
using namespace std;

//结点定义
template <class K>
struct SearchBinaryTreeNode
{
    K _key;
    SearchBinaryTreeNode<K>* _left;
    SearchBinaryTreeNode<K>* _right;


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

//搜索二叉树
template <class  K>
class SearchBinaryTree
{
    typedef SearchBinaryTreeNode<K> Node;
public:
    SearchBinaryTree()
        :_root(NULL)
    {}

    //中序遍历
    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }

    //插入
    bool Insert(const K& key)
    {
        //1.若为空树则建立一个结点给_root
        if (NULL == _root)
        {
            _root = new Node(key);
            return true;
        }

        //2.不为空,需要找到key的位置,parent记录上一个结点
        //因为搜索二叉树的结点值唯一,所以可以唯一的确认待插入的节点位置
        //cur为空时,cur即为该位置

        Node* parent = _root;
        Node* cur = _root;
        while (cur)
        {
            if (cur->_key < key)
            {
                parent = cur;
                cur = cur->_right;
            }

            else if (cur->_key > key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else
                return false;
        }


        //找到位置以后判断链接关系,当父结点的值大,则链接在父节点左侧
        if (key < parent->_key)
        {
            parent->_left = new Node(key);
            return true;
        }
        //当父结点的值小,则链接在父节点右侧
        else if (key > parent->_key)
        {
            parent->_right = new Node(key);
            return true;
        }
        else return false;
    }

    bool InsertR(const K& key)
    {
        return _InsertR(_root, key);
    }

    //寻找
    Node* Find(const K& key)
    {
        Node* cur = _root;
        while (cur)
        {
            if (cur->_key > key)
            {
                cur = cur->_left;
            }
            else if (cur->_key < key)
            {
                cur = cur->_right;
            }
            else
                return cur;
        }
        return NULL;
    }

    //递归法寻找
    Node* FindR(const K& key)
    {
        return _FindR(_root, key);
    }

    //删除一个节点
    bool Remove(const K& key)
    {

        //结点分为4类:叶子,左为空,右为空,左右均不为空
        //其中叶子节点可划归为左为空或者右为空去处理

        //找到该结点

        Node* parent = NULL;
        Node* cur = _root;
        while (cur)
        {
            if (cur->_key > key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (cur->_key < key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else
            {
                Node* del = cur;
                //1.左为空

                if (NULL == cur->_left)
                {
                    if (NULL == parent)
                    {
                        _root = cur->_right;
                    }
                    else
                    {
                        if (parent->_left == cur)
                            parent->_left = cur->_right;
                        else
                            parent->_right = cur->_right;
                    }
                }
                //右为空
                else if (NULL == cur->_right)
                {
                    if (NULL == parent)
                    {
                        _root = cur->_left;
                    }
                    else
                    {
                        if (parent->_left == cur)
                            parent->_left = cur->_left;
                        else
                            parent->_right = cur->_left;
                    }

                }
                //左右均不为空,替换法删除
                //用左子树的最右节点或者右子树的最左结点的值给待删结点
                //然后删除左子树的最右节点或者右子树的最左结点
                else
                {
                    Node* subLeft = cur->_left;
                    Node* subparent = cur;
                    while (subLeft->_right)
                    {
                        subparent = subLeft;
                        subLeft = subLeft->_right;
                    }

                    cur->_key = subLeft->_key;
                    del = subLeft;

                    if (subparent->_right == subLeft)
                        subparent->_right = subLeft->_left;
                    else
                        subparent->_left = subLeft->_left;
                }
                delete del;
                cur = NULL;
                return true;
            }
        }
        return false;
    }

    //递归法删除
    bool RemoveR(const K& key)
    {
        return _RemoveR(_root, key);
    }



protected:
    bool _RemoveR(Node*& root, const K&key)
    {

        if (key < root->_key)
            _RemoveR(root->_left,key);
        else if (key > root->_key)
            _RemoveR(root->_right, key);
        else
        {
            Node* del = root;
            if (root->_left == NULL)
                root = root->_right;
            else if (root->_right == NULL)
                root = root->_left;
            delete del;
            return true;
        }
        return false;
    }

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


    bool _InsertR(Node*& root, const K& key)
    {
        if (NULL == root)
        {
            root = new Node(key);
            return true;
        }
        else if (key > root->_key)
        {
            return _InsertR(root->_right, key);
        }
        else if (key < root->_key)
        {
            return _InsertR(root->_left, key);
        }
        else
            return false;
    }

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

protected:
    Node* _root;
};



void Test()
{
    int a[] = { 5,3,4,1,7,8,2,6,0,9 };
    SearchBinaryTree<int> t;
    for (size_t i = 0;i < sizeof(a) / sizeof(a[0]);++i)
    {
        t.Insert(a[i]);
    }
    t.Insert(12);
    t.Insert(-1);
    t.InOrder();
    SearchBinaryTreeNode<int>* ret;
    ret = t.Find(8);
    cout << "t.Find(8): " << ret->_key << endl;

    t.Remove(-1);t.InOrder();
    t.Remove(0);t.InOrder();
    t.Remove(1);t.InOrder();
    t.Remove(2);t.InOrder();
    t.Remove(3);t.InOrder();
    t.Remove(4);t.InOrder();
    t.Remove(6);t.InOrder();
    t.Remove(7);t.InOrder();
    t.Remove(8);t.InOrder();
    t.Remove(9);t.InOrder();
    t.Remove(12);t.InOrder();
    t.Remove(5);t.InOrder();//这里执行之后元素全部删除,会输出一个空行

}



    void TestR()
    {
        int a[] = { 5,3,4,1,7,8,2,6,0,9 };
        SearchBinaryTree<int> t;
        for (size_t i = 0;i < sizeof(a) / sizeof(a[0]);++i)
        {
            t.InsertR(a[i]);
        }
        t.InsertR(12);
        t.InsertR(-1);
        t.InOrder();
        SearchBinaryTreeNode<int>* ret;
        ret = t.FindR(8);
        cout << "t.FindR(8): " << ret->_key << endl;

        t.RemoveR(-1);t.InOrder();
        t.RemoveR(0);t.InOrder();
        t.RemoveR(1);t.InOrder();
        t.RemoveR(2);t.InOrder();
        t.RemoveR(3);t.InOrder();
        t.RemoveR(4);t.InOrder();
        t.RemoveR(5);t.InOrder();
        t.RemoveR(6);t.InOrder();
        t.RemoveR(7);t.InOrder();
        t.RemoveR(8);t.InOrder();
        t.RemoveR(9);t.InOrder();
        t.RemoveR(12);t.InOrder();//输出空行
    }

//搜索二叉树的应用:字典实现的基本原理
//key表示主键,value表示其附带信息(即所要查找的内容)
template <class K,class V>
struct BSTreeNode
{
    K _key;
    V _value;
    BSTreeNode<K, V>* _left;
    BSTreeNode<K, V>* _right;

    BSTreeNode(const K& key = K(), const V& value = V())
        :_key(key)
        ,_value(value)
        ,_left(NULL)
        ,_right(NULL)
    {}


};

template <class K,class V>
class BSTree
{
    typedef BSTreeNode<K, V>  Node;

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

    bool Insert(const K& key, const V& value)
    {
        return _Insert(_root, key, value);
    }

    const Node* Find(const K& key)
    {
        Node* cur = _root;
        while (cur)
        {
            if (key < cur->_key)
                cur = cur->_left;
            else if (key > cur->_key)
                cur = cur->_right;
            else
                return cur;
        }
        return false;

    }
protected:
    bool _Insert(Node*& root, const K& key, const V& value)
    {
        if (NULL == root)
        {
            root = new Node(key, value);
            return true;
        }
        else if (key < root->_key)
        {
            return _Insert(root->_left, key, value);
        }
        else if (key > root->_key)
        {
            return _Insert(root->_right, key, value);
        }
        else return false;
    }



protected:
    Node* _root;
};



void TestKV()
{
    BSTree<string, string> t;

    t.Insert("string", "字符串");
    t.Insert("some", "某些");
    t.Insert("next", "下一个");

    const BSTreeNode<string, string>* ret = t.Find("next");
    cout << ret->_value << endl;//显然结果应该是:下一个
}

运行结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值