二叉搜索树及判断一棵树是否平衡

二叉搜索树的特点:
1. 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同。
2. 左子树上所有节点的关键码(key)都小于根节点的关键码(key)。
3. 右子树上所有节点的关键码(key)都大于根节点的关键码(key)。
4. 左右子树都是二叉搜索树。
一棵二叉搜索树如下图:
《二叉搜索树及判断一棵树是否平衡》

平衡二叉树的特点:
左右子树的高度差<=1
无法达到绝对平衡是因为:如果一棵二叉树只有两个节点,则高度差永远差1。

#pragma once
#include<iostream>
#include<stack>
using namespace std;

template <class K, class V>
struct BinarySearchTreeNode
{
    K _key;
    V _value;
    BinarySearchTreeNode<K, V>* _left;
    BinarySearchTreeNode<K, V>* _right;

    BinarySearchTreeNode(K& k, V& v)
        :_key(k)
        , _value(v)
        , _left(NULL)
        , _right(NULL)
    {}
};

template <class K, class V>
class BinarySearchTree
{
    typedef BinarySearchTreeNode<K, V> Node;
public:
    BinarySearchTree()
        : _root(NULL)
    {}
    bool Insert(K key, V val)
    {
        if (_root == NULL)
        {
            _root = new Node(key, val);
            return true;
        }
        Node *cur = _root;
        Node *prev = NULL; //保存cur的前一个节点
        while (cur)
        {
            if (key < cur->_key)
            {
                prev = cur;
                cur = cur->_left;
            }
            else if (key > cur->_key)
            {
                prev = cur;
                cur = cur->_right;
            }
            else //已经存在
                return false;
        }
        Node *node = new Node(key, val);
        if (key < prev->_key)
            prev->_left = node;
        else
            prev->_right = node;
        return true;
    }

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

    bool Remove(const K& key)
    {
        if (_root == NULL)
            return false;
        if (_root->_left == NULL && _root->_right == NULL)
        {
            delete _root;
            _root = NULL;
            return true;
        }
        Node *cur = _root;
        Node *parent = NULL;
        while (cur)
        {
            if (key < cur->_key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (key > cur->_key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else //找到要删除的key
            {
                //1、cur的左孩子为空
                if (cur->_left == NULL)
                {
                    if (cur != _root)
                    {
                        if (parent->_left == cur) //判断cur在parent的左边还是右边
                            parent->_left = cur->_right;
                        else
                            parent->_right = cur->_right;
                    }
                    else //删除节点为跟节点并且左子树为空
                        _root = cur->_right;

                }
                //2、cur的右孩子为空或左右都为空
                else  if (cur->_right == NULL)
                {
                    if (cur != _root)
                    {
                        if (parent->_left == cur) //判断cur在parent的左边还是右边
                            parent->_left = cur->_left;
                        else
                            parent->_right = cur->_left;
                    }
                    else
                        _root = cur->_left;

                }
                //2、cur的左右都不为空
                if (cur->_left != NULL && cur->_right != NULL)
                {
                    Node *del = cur; //保存要删除的节点
                    parent = cur;
                    cur = cur->_right;

                    while (cur->_left) //找右子树的最左节点
                    {
                        parent = cur;
                        cur = cur->_left;
                    }
                    // 将最左节点的值赋给要删除的节点
                    del->_key = cur->_key;
                    del->_value = cur->_value;

                    if (cur == parent->_left)
                        parent->_left = cur->_right;
                    else
                        parent->_right = cur->_right;

                }
                delete cur;
                cur = NULL;
                return true;
            }
        }
        return false;
    }

    bool Insert_R(K& key, V& val)
    {
        return _Insert_R(_root, key, val);
    }

    bool Find_R(const K& key)
    {
        return _Find_R(_root, key);
    }

    bool Remove_R(const K& key)
    {
        return _Remove_R(_root, key);
    }

    void Inorder()
    {
        _Inorder(_root);
    }

    bool Isbalance()
    {
        int depth = 0;
        return _Isbalance(_root,depth);
    }

    int Heigh()
    {
        return _Height(_root);
    }
protected:
    //用后序遍历的方式遍历整课二叉树,在遍历到某一节点之后根据它左右节点的深度
    //判断当前节点是否平衡,再计算当前节点的深度。知道遍历到根节点
    bool _Isbalance(Node*& root, int& depth)
    {
        if (root == NULL)
        {
            depth = 0;
            return true;
        }
        int left = 0;
        int right = 0;
        if (_Isbalance(root->_left, left) && _Isbalance(root->_right, right))
        {
            if (abs(left - right) <= 1)
            {
                depth = (left > right ? left + 1 : right + 1);
                return true;
            }
        }
        return false;
    }

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

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

    bool _Remove_R(Node *&root, const K& key)
    {
        if (root == NULL)
            return false;
        if (key < root->_key)
            return _Remove_R(root->_left, key);
        else if (key > root->_key)
            return _Remove_R(root->_right, key);
        else
        {
            Node *del = root;
            if (root->_left == NULL)
                root = root->_right;//利用递归的特点
            else if (root->_right == NULL)
                root = root->_left;
            else
            {
                Node *parent = root;
                Node *cur = root;
                cur = cur->_right;
                while (cur->_left)
                {
                    parent = cur;
                    cur = cur->_left;
                }
                root->_key = cur->_key;
                root->_value = cur->_value;
                del = cur;

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

    int _Height(Node *&root)
    {
        if (root == NULL)
            return 0;
        int left = _Height(root->_left);
        int right = _Height(root->_right);
        return (left > right) ? left + 1 : right + 1;
    }
    //重复遍历,低效
    bool _Isbalance(Node*& root)
    {
        if (root == NULL)
            return true;

        int left = _Height(root->_left);
        int right = _Height(root->_right);
        if (abs(left - right) > 1)
            return false;
        return _Isbalance(root->_left) && _Isbalance(root->_right);
    }

    void _Inorder(Node* root)
    {
        //stack<Node*> s;
        //Node *cur = root;
        //while (cur || !s.empty())
        //{
        // while (cur)
        // {
        // s.push(cur);
        // cur = cur->_left;
        // }

        // if (!s.empty())
        // {
        // Node* top = s.top();
        // cout << top->_key << " ";
        // s.pop();
        // cur = top->_right;
        // }
        //}
        //cout << endl;
        if (root == NULL)
            return;
        if (root)
        {
            _Inorder(root->_left);
            cout << root->_key << " ";
            _Inorder(root->_right);
        }
    }
private:
    Node *_root;
};

void Test1()
{
    int a[] = { 4, 5, 6, 2, 1, 3 }; BinarySearchTree<int, int> bst; for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) { bst.Insert_R(a[i], i); } bst.Inorder(); bst.Find_R(9); bst.Find_R(10); /*bst.Remove_R(1); bst.Inorder(); bst.Remove_R(7); bst.Inorder();*/ cout << "Isbalabce ? :" << bst.Isbalance() << endl; } 
    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/yangrujing/article/details/51863734
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞