二叉搜索树

特点:

二叉查找树(Binary Search Tree),也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree)
一般具有下面的特点:

  1. 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

  2. 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

  3. 任意节点的左、右子树也分别为二叉查找树。

  4. 没有键值相等的节点(no duplicate nodes)。

分析如何删除搜索二叉树中的一个节点

①、左子树为空
使该节点的父节点左节点(右节点)指向该节点的右子树

②、右子树为空
使该节点的父节点的左节点(右节点)指向该节点的左子树

③。左右子树都不为空—->替换法删除
第一种方法:找到该节点的右子树中的最左节点(是右子树中最小的节点)和要删除的节点的键值进行替换。
第二种方法:找到该节点的左子树中的最右节点(是左子树中的最大的一个节点)和要删除的节点的键值进行替换。

代码如下:

(递归和非递归)

非递归图解:
这里写图片描述

这里写图片描述


递归删除图解:
这里写图片描述

这里写图片描述

BinarySearchTree.hpp

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include <assert.h>
using namespace std;

template<class K>
struct BinarySearchTreeNode
{
    BinarySearchTreeNode()
    :_left(NULL)
    , _right(NULL)
    {}
    BinarySearchTreeNode(const K& key)
        :_key(key)
        , _left(NULL)
        , _right(NULL)
    {}
    BinarySearchTreeNode<K>* _left;
    BinarySearchTreeNode<K>* _right;
    K _key;
};

template<class K>
class BinarySearchTree
{
    typedef BinarySearchTreeNode<K> Node;
public:
    BinarySearchTree()
        :_root(NULL)
    {}
    BinarySearchTree(Node* node)
        :_root(node)
    {}

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

    //递归插入
    bool InsertR(const K& key)
    {
        return _InsertR(, _root, key);
    }

    bool Insert(const K& key)
    {
        if (NULL == _root)
        {
            _root = new Node(key);
            return true;
        }
        Node* cur = _root;
        Node* parent = NULL;
        while (cur)
        {
            if (key > cur->_key)//需要向右子树查找
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (key < cur->_key)//需要向左子树查找
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;
            }
        }
        //注意:需要判断cur是parent的左孩子还是右孩子
        if (key > parent->_key)
        {
            parent->_right = new Node(key);
        }
        else
        {
            parent->_left = new Node(key);
        }
        return true;
    }

    const 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;
    }

    bool Remove(const K& key)
    {
        Node* cur = _root;
        Node* parent = NULL;
        Node* del = NULL;
        while (cur)
        {
            if (cur->_key > key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (cur->_key < key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else
            {
                //1.cur的左为空
                if (NULL == cur->_left)
                {
                    del = cur;
                    if (NULL == parent)//当此时的cur为根节点
                    {
                        _root = cur->_right;
                    }
                    else if (parent->_left == cur)//cur为parent的左孩子
                    {
                        parent->_left = cur->_right;
                    }
                    else //cur为parent的右孩子
                    {
                        parent->_right = cur->_right;
                    }
                }//2.cur的右为空
                else if (NULL == cur->_right)
                {
                    del = cur;
                    if (NULL == parent)
                    {
                        _root = cur->_left;
                    }
                    else if (parent->_left == cur)
                    {
                        parent->_left = cur->_left;
                    }
                    else
                    {
                        parent->_right = cur->_left;
                    }
                }//3.cur的左右都不为空(替换法删除)
                else
                {
                    //①找右子树的最左节点并删除
                    Node* subRight = cur->_right;
                    Node* parent = cur;//注意这里的parent不能是NULL(如果右子树的最左节点是根节点循环进去)
                    while (subRight->_left)
                    {
                        parent = subRight;
                        subRight = subRight->_left;
                    }
                    del = subRight;//需要删除的节点
                    cur->_key = subRight->_key;
                    //还需判断subRight是parent的左节点还是右节点
                    if (parent->_left == subRight)
                    {
                        parent->_left = subRight->_right;
                    }
                    else
                    {
                        parent->_right = subRight->_right;
                    }

                }
                delete del;
                return true;
            }
        }
        return false;
    }

    bool RemoveR(const K& key)
    {
        return _RemoveR(_root, key);
    }

    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }
    ~BinarySearchTree()
    {
        _destory(_root);
    }
private:
    bool _RemoveR(Node*& root, const K& key)
    {
        if (NULL == root)
        {
            return false;
        }
        if (root->_key < key)
        {
            return _RemoveR(root->_right, key);
        }
        else if (root->_key > key)
        {
            return _RemoveR(root->_left, key);
        }
        else
        {
            Node* del = root;
            //1.root的左节点为空
            if (NULL == root->_left)
            {
                root = root->_right;
                delete del;
            }//2.root的右节点为空
            else if (NULL == root->_right)
            {
                root = root->_left;
                delete del;
            }
            else
            {
                //3.root的左右节点都不为空
                Node* left = root->_right;
                //方法①:
                //Node* parent = root;
                //while (left->_left)
                //{
                //  parent = left;
                //  left = left->_left;
                //}
                //del = left;
                //root->_key = left->_key;//替换法删除
                //
                //if (left == parent->_left)
                //{
                //  parent->_left = left->_right;
                //}
                //else
                //{
                //  parent->_right = left->_right;
                //}
                //delete del;

                //方法②:
                while (left->_left)
                {
                    left = left->_left;
                }
                root->_key = left->_key;
                _RemoveR(root->_right, left->_key);
            }
        }
    }

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

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

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

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

    Node* _root;
};

测试代码:

#include"BinarySearchTree1.h"

void Test()
{
    int array[] = {5,3,4,1,7,8,2,6,0,9,};

    BinarySearchTree<int> tree;
    for (size_t index = 0; index < sizeof(array) / sizeof(int); ++index)
    {
        tree.Insert(array[index]);
    }
    tree.InOrder();
    if (tree.Find(7))
    {
        cout << tree.Find(7)->_key << endl;
    }

    tree.Remove(3);
    tree.Remove(5);
    tree.Remove(4);
    tree.InOrder();
    tree.Remove(1);
    tree.Remove(7);
    tree.Remove(8);
    tree.Remove(2);
    tree.InOrder();
    tree.Remove(0);
    tree.Remove(6);
    tree.InOrder();
    tree.Remove(9);
    tree.InOrder();
    tree.Remove(3);
    tree.InOrder();
    tree.Remove(5);
    tree.Remove(6);

}

void TestR()
{
    int array[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9, };
    BinarySearchTree<int> tree;
    for (size_t index = 0; index < sizeof(array) / sizeof(int); ++index)
    {
        tree.Insert(array[index]);
    }
    tree.InOrder();

    tree.RemoveR(3);
    tree.RemoveR(5);
    tree.RemoveR(4);
    tree.InOrder();
    tree.RemoveR(1);
    tree.RemoveR(7);
    tree.RemoveR(8);
    tree.RemoveR(2);
    tree.InOrder();
    tree.RemoveR(0);
    tree.RemoveR(6);
    tree.InOrder();
    tree.RemoveR(9);
    tree.InOrder();
    tree.RemoveR(3);
    tree.InOrder();
    tree.RemoveR(5);
    tree.RemoveR(6);
}

int main()
{
    //Test();
    TestR();
    return 0;
}

KeyValue结构

模拟实现一个简易的翻译工具:

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include <assert.h>
using namespace std;
#include<string>

template<class K,class V>
struct BinarySearchTreeNode
{
    BinarySearchTreeNode()
    :_left(NULL)
    , _right(NULL)
    {}
    BinarySearchTreeNode(const K& key,const V& value)
        :_key(key)
        , _left(NULL)
        , _right(NULL)
        , _value(value)
    {}
    BinarySearchTreeNode<K,V>* _left;
    BinarySearchTreeNode<K,V>* _right;
    K _key;
    V _value;
};

template<class K,class V>
class BinarySearchTree
{
    typedef BinarySearchTreeNode<K,V> Node;
public:
    BinarySearchTree()
        :_root(NULL)
    {}
    BinarySearchTree(Node* node)
        :_root(node)
    {}

    bool Insert(const K& key,const V& value)
    {
        if (NULL == _root)
        {
            _root = new Node(key,value);
            return true;
        }
        Node* cur = _root;
        Node* parent = NULL;
        while (cur)
        {
            if (key > cur->_key)//需要向右子树查找
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (key < cur->_key)//需要向左子树查找
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;
            }
        }
        //注意:需要判断cur是parent的左孩子还是右孩子
        if (key > parent->_key)
        {
            parent->_right = new Node(key,value);
        }
        else
        {
            parent->_left = new Node(key,value);
        }
        return true;
    }

     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;
    }

    bool Remove(const K& key)
    {
        Node* cur = _root;
        Node* parent = NULL;
        Node* del = NULL;
        while (cur)
        {
            if (cur->_key > key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (cur->_key < key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else
            {
                //1.cur的左为空
                if (NULL == cur->_left)
                {
                    del = cur;
                    if (NULL == parent)//当此时的cur为根节点
                    {
                        _root = cur->_right;
                    }
                    else if (parent->_left == cur)//cur为parent的左孩子
                    {
                        parent->_left = cur->_right;
                    }
                    else //cur为parent的右孩子
                    {
                        parent->_right = cur->_right;
                    }
                }//2.cur的右为空
                else if (NULL == cur->_right)
                {
                    del = cur;
                    if (NULL == parent)
                    {
                        _root = cur->_left;
                    }
                    else if (parent->_left == cur)
                    {
                        parent->_left = cur->_left;
                    }
                    else
                    {
                        parent->_right = cur->_left;
                    }
                }//3.cur的左右都不为空(替换法删除)
                else
                {
                    //①找右子树的最左节点并删除
                    Node* subRight = cur->_right;
                    Node* parent = cur;//注意这里的parent不能是NULL(如果右子树的最左节点是根节点循环进去)
                    while (subRight->_left)
                    {
                        parent = subRight;
                        subRight = subRight->_left;
                    }
                    del = subRight;//需要删除的节点
                    cur->_key = subRight->_key;
                    //还需判断subRight是parent的左节点还是右节点
                    if (parent->_left == subRight)
                    {
                        parent->_left = subRight->_right;
                    }
                    else
                    {
                        parent->_right = subRight->_right;
                    }

                }
                delete del;
                return true;
            }
        }
        return false;
    }

    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }
    ~BinarySearchTree()
    {
        _destory(_root);
    }
private:

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

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

    Node* _root;
};

测试代码:

#include"BinarySearchTree1.h"

//使用KV结构模拟一个简单的翻译工具
void Test()
{
    BinarySearchTree<string, string> dict;
    dict.Insert("tree","树");
    dict.Insert("hello","你好");
    BinarySearchTreeNode<string, string>* ret = dict.Find("tree");
    if (ret)
    {
        cout << ret->_value <<endl;
    }
    string tmp;
    while (1)
    {
        cin >> tmp;
        if (dict.Find(tmp))
        {
            cout << dict.Find(tmp)->_value << endl;
        }
    }
}

int main()
{
    Test();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值