搜索二叉树

搜索二叉树的性质

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

例如:
这里写图片描述
第二棵树中,左边的8比根节点5大,右边的4比根节点5小.不满足搜索二叉树的性质。


搜索二叉树的插入

在插入一个数后,依然满足搜索二叉树。

插入分为:
1、为空树,就直接插入。
2、从根节点依次比较,比根节点小,往左树找,比根节点大,往右树找。找到后进行插入。
3、有了这个数就直接返回,不进行插入。
非递归:

bool Insert(const K& key)//非递归插入
    {
        if (_root == NULL)//为空树,直接插入
        {
            _root = new Node(key);
            return true;
        }
        Node* cur = _root;
        Node* parent = NULL;
        while (cur)
        {
            parent = cur;
            if (key > cur->_key)//左树进行找
            {
                cur = cur->_right;
            }
            else if (key < cur->_key)//右树进行找
            {
                cur = cur->_left;
            }
            else//没找到直接返回
            {
                return false;
            }
        }
        if (key < parent->_key)
        {
            parent->_left = new Node(key);
        }
        else
        {
            parent->_right = new Node(key);
        }
        return true;
    }

递归:

bool _InsertR(Node*& cur, size_t key)//递归插入
    {
        if (cur == NULL)
        {
            cur = new Node(key);
            return true;
        }

        if (key < cur->_key)
        {
            _InsertR(cur->_left,key);
        }
        else if(key > cur->_key)
        {
            _InsertR(cur->_right,key);
        }
        else
        {
            return false;
        }
    }

搜索二叉树的查找

查找分为:
1、空树,直接返回false。
2、与根节点比较,比根节点小,左子树找,比根节点大,右子树找。找到后返回true。
3、没找到,返回false。
非递归:

bool Find(const K& key)//非递归插入
    {
        if (_root == NULL)//空树
            return false;
        Node* cur = _root;
        while (cur)
        {
            if (key < cur->_key)//左树找
            {
                cur = cur->_left;
            }
            else if (key > cur->_key)//右树找
            {
                cur = cur->_right;
            }
            else//找到
            {
                return true;
            }
        }
        return false;
    }

递归:

bool _FindR(Node*& cur, size_t key)//递归查找
    {
        if (cur == NULL)
            return false;
        if (key < cur->_key)
        {
            _FindR(cur->_left, key);
        }
        else if (key > cur->_key)
        {
            _FindR(cur->_right, key);
        }
        else
        {
            return true;
        }
        return false;
    }

搜索二叉树的删除

在删除一个数后,依然满足搜索二叉树。

删除分为:
1、空树,直接返回。
2、先找这个数,找不到返回。
3、找到后,左子树为空。
4、找到后,右子树为空。
5、找到后,左右都不为空。
大致情况为:

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

非递归:

bool Remove(const K& key)
    {
        if (_root == NULL)//空树,删除不了 ,返回false
            return false;
        Node* cur = _root;
        Node* parent = NULL;
        Node* del = NULL;
        while (cur)
        {
            if (key < cur->_key)//找的数比根节点小,在左子树上继续找
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (key > cur->_key)//找的数比根节点大,在右子树上继续找
            {
                parent = cur;
                cur = cur->_right;
            }
            else//找到了
            {
                if (cur->_left == NULL)//找到的节点的左为空
                {
                    if (parent == NULL)
                        _root = cur->_right;
                    else
                    {
                        if (cur == parent->_right)
                            parent->_right = cur->_right;
                        else
                            parent->_left = cur->_right;
                    }
                    del = cur;
                }
                else if (cur->_right == NULL)//找到的节点右为空(包括左右都为空的)
                {
                    if (parent == NULL)
                        _root = cur->_left;
                    else
                    {
                        if (cur == parent->_left)
                            parent->_left = cur->_left;
                        else
                            parent->_right = cur->_left;
                    }
                    del = cur;
                }
                else//找到的节点左右都不为空,用替换法删除(左子树的最右节点,右子树的最左节点)
                {
                    Node* subNode = cur->_left;
                    Node* tmp = cur;
                    while (subNode->_right)
                    {
                        tmp = subNode;
                        subNode = subNode->_right;
                    }
                    swap(subNode->_key, cur->_key);
                    if (subNode == tmp->_left)
                        tmp->_left = subNode->_right;
                    else
                        tmp->_right = subNode->_right;
                    del = subNode;
                }
                delete del;
                del = NULL;
                return true;
            }
        }
        return false;
    }

递归:

bool _RemoveR(Node*& cur,size_t key)
    {
        if (cur == NULL)
        {
            return false;
        }
        if (key < cur->_key)
        {
            _RemoveR(cur->_left, key);
        }
        else if (key > cur->_key)
        {
            _RemoveR(cur->_right, key);
        }
        else
        {
            Node* del = cur;
            if (cur->_left == NULL)
            {
                cur = cur->_left;
            }
            else if (cur->_right == NULL)
            {
                cur = cur->_right;
            }
            else
            {
                Node* parent = cur;
                Node* subNode = cur->_left;
                while (subNode->_right)
                {
                    parent = subNode;
                    subNode = subNode->_right;
                }
                swap(subNode->_key, cur->_key);
                if (parent->_right = subNode)
                    parent->_right = subNode->_right;
                else
                    parent->_left = subNode->_right;
                del = subNode;
            }
            delete del;
            del = NULL;
            return true;
        }
        return false;
    }

代码实现:

"SearchBinaryTree.h"
#pragma once

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)
    {}
    SearchBinaryTree(K* a, size_t n)//构造函数
    {
        _root = NULL;
        for (size_t i = 0; i < n; ++i)
        {
            InsertR(a[i]);
        }
    }

    ~SearchBinaryTree()
    {
        _Destory(_root);
    }

    bool Insert(const K& key)//非递归插入
    {
        if (_root == NULL)
        {
            _root = new Node(key);
            return true;
        }
        Node* cur = _root;
        Node* parent = NULL;
        while (cur)
        {
            parent = cur;
            if (key > cur->_key)
            {
                cur = cur->_right;
            }
            else if (key < cur->_key)
            {
                cur = cur->_left;
            }
            else
            {
                return false;
            }
        }
        if (key < parent->_key)
        {
            parent->_left = new Node(key);
        }
        else
        {
            parent->_right = new Node(key);
        }
        return true;
    }
    bool InsertR(const K& key)
    {
        return _InsertR(_root, key);
    }
    bool Remove(const K& key)
    {
        if (_root == NULL)//空树,删除不了 ,返回false
            return false;
        Node* cur = _root;
        Node* parent = NULL;
        Node* del = NULL;
        while (cur)
        {
            if (key < cur->_key)//找的数比根节点小,在左子树上继续找
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (key > cur->_key)//找的数比根节点大,在右子树上继续找
            {
                parent = cur;
                cur = cur->_right;
            }
            else//找到了
            {
                if (cur->_left == NULL)//找到的节点的左为空
                {
                    if (parent == NULL)
                        _root = cur->_right;
                    else
                    {
                        if (cur == parent->_right)
                            parent->_right = cur->_right;
                        else
                            parent->_left = cur->_right;
                    }
                    del = cur;
                }
                else if (cur->_right == NULL)//找到的节点右为空(包括左右都为空的)
                {
                    if (parent == NULL)
                        _root = cur->_left;
                    else
                    {
                        if (cur == parent->_left)
                            parent->_left = cur->_left;
                        else
                            parent->_right = cur->_left;
                    }
                    del = cur;
                }
                else//找到的节点左右都不为空,用替换法删除(左子树的最右节点,右子树的最左节点)
                {
                    Node* subNode = cur->_left;
                    Node* tmp = cur;
                    while (subNode->_right)
                    {
                        tmp = subNode;
                        subNode = subNode->_right;
                    }
                    swap(subNode->_key, cur->_key);
                    if (subNode == tmp->_left)
                        tmp->_left = subNode->_right;
                    else
                        tmp->_right = subNode->_right;
                    del = subNode;
                }
                delete del;
                del = NULL;
                return true;
            }
        }
        return false;
    }
    bool RemoveR(const K& key)
    {
        return _RemoveR(_root, key);
    }
    bool Find(const K& key)
    {
        if (_root == NULL)
            return false;
        Node* cur = _root;
        while (cur)
        {
            if (key < cur->_key)
            {
                cur = cur->_left;
            }
            else if (key > cur->_key)
            {
                cur = cur->_right;
            }
            else
            {
                return true;
            }
        }
        return false;
    }

    bool FindR(const K& key)
    {
        return _FindR(_root, key);
    }

    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }
protected:
    bool _FindR(Node*& cur, size_t key)
    {
        if (cur == NULL)
            return false;
        if (key < cur->_key)
        {
            _FindR(cur->_left, key);
        }
        else if (key > cur->_key)
        {
            _FindR(cur->_right, key);
        }
        else
        {
            return true;
        }
        return false;
    }
    bool _RemoveR(Node*& cur,size_t key)
    {
        if (cur == NULL)
        {
            return false;
        }
        if (key < cur->_key)
        {
            _RemoveR(cur->_left, key);
        }
        else if (key > cur->_key)
        {
            _RemoveR(cur->_right, key);
        }
        else
        {
            Node* del = cur;
            if (cur->_left == NULL)
            {
                cur = cur->_left;
            }
            else if (cur->_right == NULL)
            {
                cur = cur->_right;
            }
            else
            {
                Node* parent = cur;
                Node* subNode = cur->_left;
                while (subNode->_right)
                {
                    parent = subNode;
                    subNode = subNode->_right;
                }
                swap(subNode->_key, cur->_key);
                if (parent->_right = subNode)
                    parent->_right = subNode->_right;
                else
                    parent->_left = subNode->_right;
                del = subNode;
            }
            delete del;
            del = NULL;
            return true;
        }
        return false;
    }
    bool _InsertR(Node*& cur, size_t key)
    {
        if (cur == NULL)
        {
            cur = new Node(key);
            return true;
        }

        if (key < cur->_key)
        {
            _InsertR(cur->_left,key);
        }
        else if(key > cur->_key)
        {
            _InsertR(cur->_right,key);
        }
        else
        {
            return false;
        }
    }
    void _Destory(Node* cur)
    {
        if (cur == NULL)
            return;

        _Destory(cur->_left);
        _Destory(cur->_right);
        delete cur;
        cur = NULL;
    }
    void _InOrder(Node*& cur)
    {
        if (cur == NULL)
            return;
        _InOrder(cur->_left);

        cout << cur->_key << " ";
        _InOrder(cur->_right);
    }
protected:
    Node* _root;
};

void TestSearchBinaryTree()
{
    int a[] = { 5, 1, 2, 8, 3, 9, 4, 6, 7, 0 };
    SearchBinaryTree<int> t(a,sizeof(a)/sizeof(a[0]));
}
"Test.cpp"
#include <iostream>
using namespace std;
#include "SearchBinaryTree.h"

int main()
{
    TestSearchBinaryTree();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值