剑指offer之 序列化二叉树

题目描述

请实现两个函数,分别用来序列化和反序列化二叉树

二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。

二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。

思路

这道题简直恶心至极让人绝望,大概因为我是个菜逼。。
序列化:按照层次遍历得到的,不用多说
逆序列化思路:
假设 字符串是 1!2!3!4!5!#!6!#!#!#!#!#!7!#!#!
对应的结构是:
1
2 3
4 5 NULL 6
NULL NULL NULL NULL NULL 7
我们的序列化算法中默认NULL是没有子树的,因此第三层的NULL没有子树,第四层只有4,5,6的子树。

首先将字符串转换为一个结点队列
其次是重组二叉树

过程如下:
First :
q_Tree_2 1
q_Tree_1 2 3 4 5 NULL 6 NULL NULL NULL NULL NULL 7

这一步将1pop出来,把2和3挨个pop出来,并安排为1的左右子树,并将2和3压到q_Tree_2 中

Second:
q_Tree_2 2 3
q_Tree_1 4 5 NULL 6 NULL NULL NULL NULL NULL 7

依次将2和3pop出来,将4,5NULL,6pop出来,但是需要注意的是,3的左子树是NULL,不需要给他分配子结点,则不需将NULL压入q_Tree_2

Third:
q_Tree_2 4 5 6
q_Tree_1 NULL NULL NULL NULL NULL 7

Four:
q_Tree_2 7
q_Tree_1

Finish!

代码

class Solution {
public:
    queue<TreeNode*> q_Tree_1;
    queue<TreeNode*> q_Tree_2;
    /* 我这里用了层次遍历,这个就不赘述了,大家应该都知道*/
    char* Serialize(TreeNode *root) {   
        char* res;
        string serial;
        if (root == NULL)
        {
            res = new char[3]();
            res[0] = '#';
            res[1] = '!';
            return res;
        }
        queue<TreeNode*> q_Tree;
        q_Tree.push(root);
        while (q_Tree.size() > 0)
        {
            TreeNode* current = q_Tree.front();
            q_Tree.pop();
            if (current == NULL)
            {
                serial = serial + '#' + '!';
            }
            else
            {
                serial = serial + to_string(current->val) + '!';
                if (current->left == NULL && current->right == NULL)
                {
                    continue;
                }
                else
                {
                    q_Tree.push(current->left);
                    q_Tree.push(current->right);
                }

            }
        }
        int a = serial.size();
        char* res_2= new char[a + 1]();
        memcpy(res_2, serial.c_str(), a);
        return res_2;
    }
    /*  这个是逆序列函数,将一段字符串换成一堆结点保存到q_Tree_1中 */
    TreeNode* Deserialize(char *str) {
        string s = str;
        if (s.size() == 0 || s[0] == '#')
        {
            return NULL;
        }
        int end = 0;
        while (end < s.size())
        {
            TreeNode* node = sring_node(s, end, s.find("!", end + 1));
            q_Tree_1.push(node);
            if (end == s.size())
                break;
            else
                end = s.find("!", end + 1) + 1;
        }
        TreeNode* root;
        root = Deserialize_sub();
        return root;
    }
    /* 这个函数是将一段字符转换为数字,start标志上一个!的下一位,end表示这次找到的!,二者就将这个结点数字对应的字符取出*/
    TreeNode* sring_node(string s,int start, int end)
    {
        int number = 0;
        for (int i = start; i < end; i++)
        {
            if (s[i] == '#')
            {
                return NULL;
            }
            else
            {
                number = number + (s[i] - '0')*pow(10, end - i - 1);
            }
        }
        TreeNode* node = new TreeNode(number);
        return node;
    }
        /* 这个函数是将结点重构成树,利用两个队列,队列1保存剩余结点,队列2保存下次分配子结点的那些结点。特别需要注意的!调了2个小时才明白的!每次队列1pop之后,需要判断pop出来的是不是NULL,NULL的就不push到队列2中,因为NULL没有子树*/
    TreeNode* Deserialize_sub()
    {
        if (q_Tree_1.size() == 0)
		    return NULL;
        int count = 0;
        TreeNode* root;
        root = q_Tree_1.front();
        q_Tree_1.pop();
        q_Tree_2.push(root);
        while (q_Tree_1.size()>0)
        {
            int size = q_Tree_2.size();
            for (int i = 0; i < size; i++)
            {
                TreeNode* node = q_Tree_2.front();
                q_Tree_2.pop();
                TreeNode* node_left = q_Tree_1.front();
                q_Tree_1.pop();
                node->left = node_left;
                TreeNode* node_right = q_Tree_1.front();
                q_Tree_1.pop();
                node->right = node_right;
                if(node_left) q_Tree_2.push(node_left);
                if(node_right) q_Tree_2.push(node_right);
            }
            count++;
        }
            return root;
        }
};
发布了85 篇原创文章 · 获赞 0 · 访问量 395

猜你喜欢

转载自blog.csdn.net/weixin_38312163/article/details/104853889