04.29_111期_C++_map&set

#pragma once

#include <iostream>
#include <string>
#include <set>
#include <map>
#include <vector>
#include <assert.h>

using namespace std;

template<class K, class V>
struct AVLTreeNode
{
    AVLTreeNode(const pair<K, V>& kv)
        :_left(nullptr)
        , _right(nullptr)
        , _parent(nullptr)
        , _kv(kv)
        , _bf(0)
    {}
    AVLTreeNode<K, V>* _left;
    AVLTreeNode<K, V>* _right;
    //为了实现通过孩子找父亲,会在AVLTree的每个结点中多加一个成员
    // 这个成员是 指向其父亲结点的 指针
    AVLTreeNode<K, V>* _parent;
    pair<K, V> _kv;

    int _bf;

};

//AVL树 是 平衡二叉树 和 搜索二叉树的交集
template<class K, class V>
class AVLTree
{
    typedef AVLTreeNode<K, V> Node;
public:
    // AVL树的insert方法必须满足的条件
    // 按搜索树的的规则插入,按平衡二叉树的规则更新 _bf因子:
    // 平衡衡二叉树的规则:
    // rule0: 树中每一个结点的左右子树的高度之差的绝对值小于等于1
    // 更新_bf 因子的规则如下:
    // rule1: _bf = 右子树的高度 - 左子树的高度
    //     case1.1: 插入的结点是其父亲结点的左孩子,那么应将该父亲结点的平衡因子 减 1
    //     case1.2: 插入的结点是其父亲结点的右孩子,那么应将该父亲结点的平衡因子 加 1
    // rule2: 每次插入结点时,要不断更新这个新结点 对应的祖先 的_bf因子
    //     更新的情况有以下几种:下面称当前更新到的结点的父亲结点为α
    //     case2.1: α的平衡因子 == 0,父亲的两颗子树的高度不变,不再继续往上更新,插入结束
    //     case2.2: α的平衡因子 == 1或-1,父亲有一颗子树的高度变了,继续往上更新
    //     case2.3: α的平衡因子 == 2或-2,父亲的两颗子树已经不满足rule0,需要旋转处理
    //    注意:由于AVLTree类创建的对象全是平衡二叉树,那么插入节点后 按照rule2更新完平衡因子之后
    //          结点的平衡因子应仍然只从 -1,1,0这三个值中取值
    bool Insert(const pair<K, V>& kv)
    {
        if (_root == nullptr)
        {
            _root = new Node(kv);
            return true;
        }
        Node* parent = nullptr;
        Node* cur = _root;
        while (cur)
        {
            if (cur->_kv.first < kv.first)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_kv.first > kv.first)
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;
            }
        }
        cur = new Node(kv);

        if (parent->_kv.first < kv.first)
        {
            parent->_right = cur;
        }
        else
        {
            parent->_left = cur;
        }
        cur->_parent = parent;

        while (parent)
        {
            if (cur == parent->_left)
            {
                parent->_bf--;
            }
            else
            {
                parent->_bf++;
            }

            if (parent->_bf == 0)
            {
                //更新结束
                break;
            }
            else if ((parent->_bf == 1) || (parent->_bf == -1))
            {
                //继续往上更新
                cur = parent;
                parent = parent->_parent;
            }
            else if ((parent->_bf == 2) || (parent->_bf == -2))
            {
                //需要通过旋转调整当前所遍历到的结点的左右子树的高度
                if (parent->_bf == -2 && cur->_bf == -1)
                {
                    Rotateright(parent);
                }
                else if (parent->_bf == 2 && cur->_bf == 1)
                {
                    Rotateleft(parent);
                }
                else if (parent->_bf == -2 && cur->_bf == -1)
                {

                }
                else
                {

                }
                break;
            }
            else
            {
                assert(false);
            }
        }


        return true;
    }

    Node* Find(const pair<K, V>& kv)
    {
        Node* cur = _root;
        while (cur)
        {
            if (cur->_kv.first < kv.first)
            {
                cur = cur->_right;
            }
            else if (cur->_kv.first > kv.first)
            {
                cur = cur->_left;
            }
            else
            {
                return cur;
            }
        }
        return cur;
    }

//    bool Erase(const K& key)
//    {
//        if (_root == nullptr)
//        {
//            return false;
//        }
//        Node* parent = nullptr;
//        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
//            {
//                if (cur->_left == nullptr)
//                {
//                    if (cur == _root)
//                    {
//                        _root = cur->_right;
//                    }
//                    else
//                    {
//                        if (cur == parent->_left)
//                        {
//                            parent->_left = cur->_right;
//                        }
//                        else
//                        {
//                            parent->_right = cur->_right;
//                        }
//                    }
//                }
//                else if (cur->_right == nullptr)
//                {
//                    if (cur == _root)
//                    {
//                        _root = cur->_left;
//                    }
//                    else
//                    {
//                        if (cur == parent->_left)
//                        {
//                            parent->_left = cur->_left;
//                        }
//                        else
//                        {
//                            parent->_right = cur->_left;
//                        }
//                    }
//                }
//                else
//                {
//                    Node* rightMinParent = cur;
//                    Node* rightMin = cur->_right;
//                    while (rightMin->_left)
//                    {
//                        rightMinParent = rightMin;
//                        rightMin = rightMin->_left;
//                    }
//                    swap(cur->_key, rightMin->_key);
//
//                    if (rightMinParent->_left == rightMin)
//                    {
//                        rightMinParent->_left = rightMin->_right;
//                    }
//                    else
//                    {
//                        rightMinParent->_right = rightMin->_right;
//                    }
//                    delete rightMin;
//                }
//                return true;
//            }
//        }
//        return false;
//    }
//
    void InOrder()
    {
        shelledInOrder(_root);
        cout << endl;
    }

    // 旋转的本质:
    //       在最小的范围内将一个结点的
    //       左子树的一部分链接到右子树上  或  右子树的一部分链接到左子树上
    // 旋转后达到的结果:
    //       1. 该节点的左右子树 高度相同,即平衡了
    //       2. 该节点对应下的整棵树  与  旋转前的树 高度相同
    
    // 要对 结点进行右旋来调成平衡,这个结点的左右子树需要满足的条件有:
    //      1. 这个结点的左子树的高度比右子树的高度   高两层
    //         表现为  增加了新的结点之后,左子树的高度    加一
    //      2. 而且无法通过只改变左子树内部的连接关系就把高度减小
    //         表现为  增加了新的结点之后,左子树内部还是平衡的
    void Rotateright(Node* parent)
    {
        //右旋要看四个结点,三个双向链接,两种特殊情况
        //四个结点:
        //      1. 当前结点            2. 当前结点的父节点
        //      3. 当前结点的左孩子   4. 当前结点的左孩子的右孩子结点
        //三个双向链接:
        //      一、  2. 和  1. 的父子关系 
        //      二、  1. 和  3. 的父子关系 
        //      三、  3. 和  4. 的父子关系 
        //两种特殊情况:
        //      case1: 1. 就是整棵树的 根节点,导致一、需要加if() else{}判断
        //      case2: 4. 是一个空结点,导致三、需要加if() else{}判断
        Node* subLnode = parent->_left;
        Node* subLRnode = subLnode->_right;
        Node* pPnode = parent->_parent;

        parent->_left = subLRnode;
        if (subLRnode)
        {
            subLRnode->_parent = parent;
        }
        subLnode->_right = parent;

        parent->_parent = subLnode;
        if (parent == _root)
        {
            _root = subLnode;
            _root->_parent = nullptr;
        }
        else
        {
            if (pPnode->_left == parent)
            {
                pPnode->_left = subLnode;
            }
            else
            {
                pPnode->_right = subLnode;
            }
            subLnode->_parent = pPnode;
        }

        //注意!!!!!!!!!!!!!!!!!!!!!!!
        //右旋的结果是:
        //      1. 将所针对的结点和该结点的左孩子结点的父子关系颠倒
        //      2. 将所针对结点  和  该节点的左孩子结点的  平衡因子调为0
        parent->_bf = subLnode->_bf = 0;
    }

    void Rotateleft(Node* parent)
    {
        Node* subRnode = parent->_right;
        Node* subRLnode = subRnode->_left;
        Node* pPnode = parent->_parent;

        parent->_right = subRLnode;
        if (subRLnode)
        {
            subRLnode->_parent = parent;
        }
        subRnode->_left = parent;

        parent->_parent = subRnode;
        if (parent == _root)
        {
            _root = subRnode;
            _root->_parent = nullptr;
        }
        else
        {
            if (pPnode->_left == parent)
            {
                pPnode->_left = subRnode;
            }
            else
            {
                pPnode->_right = subRnode;
            }
            subRnode->_parent = pPnode;
        }

        parent->_bf = subRnode->_bf = 0;
    }

private:
    void shelledInOrder(Node* root)
    {
        if (root == nullptr)
        {
            return;
        }
        shelledInOrder(root->_left);
        cout << root->_kv.first << ":" << root->_kv.second << endl;
        shelledInOrder(root->_right);
    }

private:
    Node* _root = nullptr;
};

void testAVLTree1()
{
    int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };
    AVLTree<int, int> t1;
    for (auto e : a)
    {
        t1.Insert({e, e});
    }
    t1.InOrder();

}

//void testBSTree2()
//{
//    key_value::BSTree<string, string> dict;
//    dict.Insert("string", "字符串");
//    dict.Insert("left", "左");
//    dict.Insert("insert", "插入");
//
//    string str;
//    while (cin >> str)
//    {
//        key_value::BSTreeNode<string, string>* ret = dict.Find(str);
//        if (ret)
//        {
//            cout << ret->_value << endl;
//        }
//        else
//        {
//            cout << "无此单词,请重新输入" << endl;
//        }
//    }
//
//}
//
//void testBSTree3()
//{
//    string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "西瓜", "西瓜" };
//    key_value::BSTree<string, int> countTree;
//    for (const auto& str : arr)
//    {
//        auto ret = countTree.Find(str);
//        if (ret == nullptr)
//        {
//            countTree.Insert(str, 1);
//        }
//        else
//        {
//            ret->_value++;
//        }
//    }
//    countTree.InOrder();
//}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值