二叉搜索树

一:二叉搜索树的性质:
1:每个节点都有一个作为搜索的关键码(key),所有节点的关键码互不相同;
2:左子树所有节点的关键码(key)都小于右子树的关键码(key)
3 : 左子树所有节点的关键码(key)都小于右子树的关键码(key)

4:左右字子树都是二叉搜索树


二:二叉树的插入:
分三步:
1:空树的情况,直接把节点插入到根节点
2:不为空,比较插入值的关键码与根节点的关键码,确定插入的位置
3:插入后结果任然为一颗二叉搜索树
如:我们希望插入10;parent和cur都是从根节点开始,10比5大,走右子树,比7大继续右子树,每次走的一步parent都置为当前值(cur),cur继续向下走,一直到9。最后把值插入到9的后面。
插入后仍然为二叉搜索树


bool Insert(const K&key)
    {
        //为空
        if (_root == NULL)
        {
            _root = new Node(key);
            return true;
        }
        //不为空
        Node*cur = _root;
        Node *parent = NULL;
        while (cur)
        {
            if (cur->_key < key)//右边
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key>key)//左边
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;//不存在
            }
        }
        //key值存在
        Node*tmp = new Node(key);
        if (parent->_key < key)//右边
        {
            parent->_right = tmp;;
        }
        else //左边
        {
            parent->_left = tmp;   
        }   
        return false;//值相等
    }
三:二叉树的查找
1:查找的值与根节点的值比较,从根开始,查找的值比根的值小走左子树,比根的值大走右子树,直到遍历完这个二叉搜索树,结果有两种找到,找不到;
//查找
 bool Find(const K&key)
    {
        Node*cur = _root;
        while (cur)
        {
            if (cur->_key < key)//右边
            {
                cur = cur->_right;
            }
            else if (cur->_key >key)//左边
            {
                cur = cur->_left;
            }
            else
            {
                cout << "找到了" <<cur->_key<< endl;
                return true;
            }
        }
        return false;//没找到
    }


四:二叉树的删除:
删除的算法我们可以分为4种情况:
1:删除叶子节点
  
      Node*cur = _root;
        Node*parent = NULL;    
      //叶子节点直接删除
                if (cur->_left == NULL)
                {
                    if (parent &&cur == parent->_left)//左为空
                    {
                        parent->_left = NULL;

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

2:删除非叶子点

替换法删除找最右孩子的左子树,或者是最左孩子的右子树,,先交换要删除的节点与其右孩子交换,然后把要删除的节点右孩子赋给父亲的右孩子。最后删除当前结点。

3:  删除根节点;


 
4:删除所有节点;
删除算法
bool Remove(const K&key)
    {
        //为空
        if (_root == NULL)
        {
            return false;
        }
        //不为空  
        Node*cur = _root;
        Node*parent = NULL;
        while (cur)
        {
            if (cur->_key < key)//右边
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key>key)//左边
            {
                parent = cur;
                cur = cur->_left;
            }
            //要删除的节点就是当前节点
            else
            {
                //叶子节点直接删除
                if (cur->_left == NULL)
                {
                    if (parent &&cur == parent->_left)//左为空
                    {
                        parent->_left = NULL;

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

                //只有一个孩子节点
                else if (cur->_left == NULL || cur->_right == NULL)
                {
                    if (cur->_left != NULL)//只有左孩子
                    {
                        if (parent == NULL)
                        {
                            _root = cur->_left;
                        }
                        else if (parent->_left = cur)//左子树
                        {
                            parent->_left = cur->_left;
                        }
                        else
                        {
                            parent->_right = cur->_left;
                        }
                        delete cur;
                    }
                    else if (cur->_right != NULL)//只有右孩子
                    {
                        if (parent == NULL)
                        {
                            _root = cur->_right;
                        }
                        else if (parent->_right == cur)
                        {
                            parent->_left = cur->_right;
                        }
                        else
                        {
                            parent->_right = cur->_right;
                        }
                        delete cur;
                    }
                }

                //有两个孩子(替换法删除)找最右孩子的左子树
                else
                {
                    Node* subRight = cur->_right;
                    Node* subParent = cur;
                    Node*del = NULL;
                    while (subRight->_left)
                    {
                        subParent = subRight;
                        subRight = subRight->_left;
                    }

                    cur->_key = subRight->_key;
                    if (subParent->_right == subRight)
                        subParent->_right = subRight->_right;
                    else
                        subParent->_left = subRight->_left;
                    delete subRight;
                }
                return true;
            }
        }
        return false;
    }//没有找到删除值

完整代码:

.h文件
#pragma once
#include<iostream>
using namespace std;
template<class K>
struct BinarySerachTreeNode
{
    K _key;
    BinarySerachTreeNode<K> *_left;
    BinarySerachTreeNode<K> *_right;

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

template < class K>
class BinarySerachTree
{
    typedef BinarySerachTreeNode<K> Node;
public:
    BinarySerachTree()
        :_root(NULL)
    {}
    //插入
    bool Insert(const K&key)
    {
        //为空
        if (_root == NULL)
        {
            _root = new Node(key);
            return true;
        }
        //不为空
        Node*cur = _root;
        Node *parent = NULL;
        while (cur)
        {
            if (cur->_key < key)//右边
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key>key)//左边
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;//不存在
            }
        }
        //key值存在
        Node*tmp = new Node(key);
        if (parent->_key < key)//右边
        {
            parent->_right = tmp;;

        }
        else //左边
        {
            parent->_left = tmp;   
        }   
        return true;
    }
    //查找
    bool Find(const K&key)
    {
        Node*cur = _root;
        while (cur)
        {
            if (cur->_key < key)//右边
            {
                cur = cur->_right;
            }
            else if (cur->_key >key)//左边
            {
                cur = cur->_left;
            }
            else
            {
                cout << "找到了" <<cur->_key<< endl;
                return true;
            }
        }
        return false;//没找到
    }
    //删除
    bool Remove(const K&key)
    {
        //为空
        if (_root == NULL)
        {
            return false;
        }
        //不为空
        Node*cur = _root;
        Node*parent = NULL;
        while (cur)
        {
            if (cur->_key < key)//右边
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key>key)//左边
            {
                parent = cur;
                cur = cur->_left;
            }
            //要删除的节点就是当前节点
            else
            {
                //叶子节点直接删除
                if (cur->_left == NULL)
                {
                    if (parent &&cur == parent->_left)//左为空
                    {
                        parent->_left = NULL;

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

                //只有一个孩子节点
                else if (cur->_left == NULL || cur->_right == NULL)
                {
                    if (cur->_left != NULL)//只有左孩子
                    {
                        if (parent == NULL)
                        {
                            _root = cur->_left;
                        }
                        else if (parent->_left = cur)//左子树
                        {
                            parent->_left = cur->_left;
                        }
                        else
                        {
                            parent->_right = cur->_left;
                        }
                        delete cur;
                    }
                    else if (cur->_right != NULL)//只有右孩子
                    {
                        if (parent == NULL)
                        {
                            _root = cur->_right;
                        }
                        else if (parent->_right == cur)
                        {
                            parent->_left = cur->_right;
                        }
                        else
                        {
                            parent->_right = cur->_right;
                        }
                        delete cur;
                    }
                }

                //有两个孩子(替换法删除)找最右孩子的左子树
                else
                {
                    Node* subRight = cur->_right;
                    Node* subParent = cur;
                    Node*del = NULL;
                    while (subRight->_left)
                    {
                        subParent = subRight;
                        subRight = subRight->_left;
                    }

                    cur->_key = subRight->_key;
                    if (subParent->_right == subRight)
                        subParent->_right = subRight->_right;
                    else
                        subParent->_left = subRight->_left;
                    delete subRight;
                }
                return true;
            }
        }
        return false;
    }//没有找到删除值
    //中序
    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }
protected:
    void _InOrder(Node*root)
    {
        Node*cur = root;
        if (cur == NULL)
        {
            return ;
        }
        _InOrder(cur->_left);
        cout << cur->_key << " ";
        _InOrder(cur->_right);
    }
protected:
    Node* _root;
};


void TestBinarySearchTree()
{
    BinarySerachTree<int> b;
    int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
    for (int i = 0; i <sizeof(a) / sizeof(a[0]);i++)
    {
        b.Insert(a[i]);
    }
    b.InOrder();
    b.Find(3);

    b.Remove(9);
    b.InOrder();

    b.Remove(0);
    b.InOrder();

    b.Remove(2);
    b.InOrder();

    b.Remove(7);
    b.InOrder();

    b.Remove(5);
    b.InOrder();

    b.Remove(1);
    b.Remove(3);
    b.Remove(4);
    b.Remove(6);
    b.Remove(8);
    b.InOrder();
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值