二叉平衡树插入查找和持久化 | 青训营笔记

139 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记

3.AVL树插入查找

(1)AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么AVL树的插入过程可以分为两步:

  1. 按照二叉搜索树的方式插入新节点
  2. 调整节点的平衡因子

    bool Insert(const pair<K, V>& kv)
    {
        if (_root == nullptr)
        {
            _root = new Node(kv);
            return true;
        }
        Node* cur = _root;
        Node* parent = nullptr;
        while (cur)
        {
            if (kv.first > cur->_kv.first)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (kv.first < cur->_kv.first)
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;
            }
        }
        cur = new Node(kv);
        if (kv.first > parent->_kv.first)
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        else
        {
            parent->_left = cur;
            cur->_parent = parent;
        }
​
        //更新平衡因子以及AVL树的旋转
        while (parent)
        {
            //更新双亲的平衡因子
            if (cur == parent->_right)
            {
                parent->_bf++;
            }
            else
            {
                parent->_bf--;
            }
​
            //检测双亲的平衡因子是否满足(0,-1,1)
            if (parent->_bf == 0)
            {
                break;
            }
            else if (parent->_bf == 1 || parent->_bf == -1)
            {
                //继续向上调整parent,更新并检测平衡因子
                cur = parent;
                parent = parent->_parent;
            }
            else if (parent->_bf == 2 || parent->_bf == -2)
            {
                //双亲的平衡因子为正负2,违反了AVL树的平衡性,需要对以Parent为根的树进行旋转处理
                if (parent->_bf == 2)
                {
                    if (cur->_bf == 1)
                    {
                        //左单旋
                        RotateL(parent);
                    }
                    else if (cur->_bf == -1)
                    {
                        //双旋:先右单旋再左单旋
                        RotateRL(parent);
                    }
                }
                else if (parent->_bf == -2)
                {
                    if (cur->_bf == -1)
                    {
                        //右单旋
                        RotateR(parent);
                    }
                    else if (cur->_bf == 1)
                    {
                        //双旋:先左单旋再右单旋
                        RotateLR(parent);
                    }
                }
                //旋转完成后,parent所在树的高度恢复到了插入节点之前的高度
                //如果parent所在树是子树,也不会对上层有影响,因此不再更新上层的平衡因子了
                break;
            }
        }
        return true;
    }

(2)平衡二叉搜索树中序遍历可得到一个有序的序列。因此可以直接通过中序遍历查找所需元素。

4.序列化反序列化

序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。

参考leetcode449题leetcode.cn/problems/se… 序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。

设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。

编码的字符串应尽可能紧凑。

 

示例 1:

输入:root = [2,1,3] 输出:[2,1,3]


class Codec {
public:
    string path;
    string serialize(TreeNode* root) {
        dfs(root);
        return path;
    }
    void dfs(TreeNode* root){
        if(root == NULL){
            path += "#,";
            return;
        } 
        path +=to_string(root->val) + ",";
        dfs(root->left);
        dfs(root->right);
    }
​
    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        int u = 0;
        return dfs_t(data, u);
    }
    TreeNode* dfs_t(string &data, int &u){
        if(data[u] == '#'){
            u += 2;
            return NULL;
        }
        int k = u;
        while(data[u] != ',') u++;
        auto p = new TreeNode(stoi(data.substr(k, u - k)));
        u++;
        p->left = dfs_t(data, u);
        p->right = dfs_t(data, u);
        return p;
    }
};

\