zoukankan      html  css  js  c++  java
  • 剑指offer(61):序列化二叉树

    题目描述

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

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

    例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己的函数来解析回这个二叉树
     
    思路:自己想的思路是采用层次遍历,序列化的时候使用队列,如果结点为空,字符串+“#!”,如果不为空,则字符串+“结点值!”;反序列化过程将字符串按照!分割成字符串数组,然后如果为# ,则为空,否则创建该结点,在反序列化的过程也需要一个队列辅助。
    java层次遍历:
    import java.util.*;
    public class Solution {
        String Serialize(TreeNode root) {
            StringBuffer sb = new StringBuffer();
            //String traverseOrder = "";
            if(root != null){
                Queue<TreeNode> qRoot = new LinkedList<>();
                TreeNode q;
                
                qRoot.add(root);
                while(!qRoot.isEmpty()){
                    q = qRoot.poll();
                    if(q == null) sb.append("#!"); //traverseOrder+="#!";
                    else{
                        sb.append(q.val+"!");
                        //traverseOrder+=q.val+"!";
                        qRoot.add(q.left);
                        qRoot.add(q.right);
                    }
                }
            }
            // return traverseOrder;
            return sb.toString();
      }
        TreeNode Deserialize(String str) {
           if(str.length() == 0) return null;
            
            String[] traverseOrder = str.split("!");
            TreeNode root = new TreeNode(Integer.parseInt(traverseOrder[0]));
            
            Queue<TreeNode> qRoot = new LinkedList<>();
            qRoot.add(root);
            TreeNode p = qRoot.poll();
            for(int i=1;i<traverseOrder.length;i = i+2){
                TreeNode pLeft = null;
                TreeNode pRight = null;
                if(!"#".equals(traverseOrder[i]))
                    pLeft = new TreeNode(Integer.parseInt(traverseOrder[i]));
                if(!"#".equals(traverseOrder[i+1]))
                    pRight = new TreeNode(Integer.parseInt(traverseOrder[i+1]));
                p.left = pLeft;
                p.right = pRight;
                if(p.left != null) qRoot.add(p.left);
                if(p.right != null) qRoot.add(p.right);
                p = qRoot.poll();
            }
            return root;
      }
    }

    思路:参考https://www.nowcoder.com/profile/767712797/codeBookDetail?submissionId=85270378进行先序遍历的实现,一般情况我们需要已知中序遍历和先序遍历或者中序遍历和后序遍历才能构造出二叉树,但是由于我们序列化的过程中引入了空节点(用#代表空节点),因此在反序列化的时候可以通过判断是否为#,而得到终止位置。

    题目中C++提供的是char*类型,使用略有生疏

    class Solution {
    public:
        char* Serialize(TreeNode *root) {   
            if(!root) return "#";
            string res = to_string(root->val);
            res.push_back(',');
            
            char* left = Serialize(root->left);
            char* right = Serialize(root->right);
            
            char* ret = new char[res.length()+strlen(left)+strlen(right)];
            
            strcpy(ret, res.c_str());
            strcat(ret, left);
            strcat(ret, right);
            
            return ret;
        }
       
        TreeNode* Deserialize(char *str) {
            return Deserialize2(str);
            
        }
        
        TreeNode* Deserialize2(char *&s){
            if(*s == '#'){
                s++;
                return nullptr;
            }
            int num = 0;
            while(*s!=','){
                num = num*10+(*s - '0');
                s++;
            }
            ++s;
            TreeNode* root = new TreeNode(num);
            root->left = Deserialize2(s);
            root->right = Deserialize2(s);
            return root;
        }
    };
  • 相关阅读:
    junit spring
    DFU协议介绍
    USB枚举过程
    触摸板单点描述符
    Linux下使用codeblocks交叉编译ARM-LINUX-GCC程序
    树莓派 原理图 摄像头接口定义
    usb描述符详细讲解
    常用的算法思想
    STM32f407 DCMI方式驱动 OV2640
    linux echo命令-转
  • 原文地址:https://www.cnblogs.com/ttzz/p/13510672.html
Copyright © 2011-2022 走看看