序列化和反序列化二叉树

今天练习算法,在leetcode上做了一道练习,照着上面的分析写了下面的代码,编译执行也都没有问题,在这里写写。

这里采用二叉树的先序遍历方式作为序列化和反序列化的主要思路,对空的子树用‘#‘进行记录。

在序列化的时候,使用递归进行先序遍历,递归执行到空节点,则保存‘#‘并返回;否则记录当前节点的值,并继续对其左右节点进行遍历。

同样,在反序列化的时候,当前读到的值作为新子树的根节点root,下一个读到的节点则为root节点的左子树root->left,并将当前索引值的引用传入下一步的递归,直到读到‘#‘递归层层返回;因为递归调用传入了当前值的引用,所以递归返回到root时,下一个读到的值将会用来初始化root的右子树root->right。

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <fstream>
  4 #include <vector>
  5 #include <cstring>
  6 #include <vld.h>
  7
  8 using namespace std;
  9
 10 struct TreeNode
 11 {
 12     int i_val;
 13     TreeNode *p_left;
 14     TreeNode *p_right;
 15     TreeNode() : i_val(0), p_left(0), p_right(0) {}
 16     TreeNode(int val) : i_val(val), p_left(0), p_right(0) {}
 17     TreeNode(const TreeNode &treeNode) : i_val(treeNode.i_val), p_left(treeNode.p_left), p_right(treeNode.p_right) {}
 18     TreeNode &operator=(const TreeNode &treeNode)
 19     {
 20         if(this != &treeNode)
 21         {
 22             this->i_val = treeNode.i_val;
 23             this->p_left = treeNode.p_left;
 24             this->p_right = treeNode.p_right;
 25         }
 26         return *this;
 27     }
 28 };
 29
 30 // 读到的字符是否是分隔符
 31 inline bool isToken(char c, string &token)
 32 {
 33     for(string::iterator it = token.begin(); it != token.end(); ++it)
 34     {
 35         if(c == (*it))
 36         {
 37             return true;
 38         }
 39     }
 40     return false;
 41 }
 42
 43 // 读到的内容是否是数字
 44 inline bool isNumber(string &str)
 45 {
 46     if(str.size() == 0)
 47     {
 48         return false;
 49     }
 50     for(int i = 0; i < str.size(); ++i)
 51     {
 52         if(str[i] < ‘0‘ || str[i] > ‘9‘)
 53         {
 54             return false;
 55         }
 56     }
 57     return true;
 58 }
 59
 60 // 字符串转数字
 61 int str2int(string &str)
 62 {
 63     int ret = 0;
 64     for(int i = 0; i < str.size(); ++i)
 65     {
 66         ret = ret * 10 + (str[i] - ‘0‘);
 67     }
 68     return ret;
 69 }
 70
 71 // 从文件中读序列化后的内容
 72 // 这里读到的内容是
 73 // 30 10 50 # # # 20 45 # # 35 # #
 74 vector<string> readFile(ifstream &in, string &token)
 75 {
 76     if(!in.is_open())
 77     {
 78         cout << "Error during opening the file." << endl;
 79         exit(1);
 80     }
 81     char c;
 82     string word;
 83     vector<string> vec_Str;
 84     while(in.get(c))
 85     {
 86         if(!isToken(c, token))
 87         {
 88             word.push_back(c);
 89             continue;
 90         }
 91
 92         if(word.length() > 0)
 93         {
 94             vec_Str.push_back(string(word.begin(), word.end()));
 95             word.clear();
 96         }
 97     }
 98     if(word.length() > 0)
 99     {
100         vec_Str.push_back(string(word.begin(), word.end()));
101     }
102
103     return vec_Str;
104 }
105
106 // 反序列化二叉树
107 TreeNode *DeserializeTree(int &cur, vector<string> &vec_SerialTree)
108 {
109     if(cur < 0 || cur >= vec_SerialTree.size() || vec_SerialTree.size() == 0 || !isNumber(vec_SerialTree[cur]))
110     {
111         return 0;
112     }
113     TreeNode *p_Node = new TreeNode(str2int(vec_SerialTree[cur]));
114     cur = cur + 1;
115     p_Node->p_left = DeserializeTree(cur, vec_SerialTree);
116     cur = cur + 1;
117     p_Node->p_right = DeserializeTree(cur, vec_SerialTree);
118
119     return p_Node;
120 }
121
122 // 序列化二叉树
123 void SerializeTree(TreeNode *p_Root, ostream &out)
124 {
125     if(!p_Root)
126     {
127         out << "# ";
128     }
129     else
130     {
131         out << p_Root->i_val << " ";
132         SerializeTree(p_Root->p_left, out);
133         SerializeTree(p_Root->p_right, out);
134     }
135 }
136
137 // 释放资源
138 void DestroyTree(TreeNode **p_Root)
139 {
140     if(!p_Root || !(*p_Root))
141     {
142         return;
143     }
144     DestroyTree(&((*p_Root)->p_left));
145     DestroyTree(&((*p_Root)->p_right));
146     delete *p_Root;
147     p_Root = 0;
148 }
149
150 int main()
151 {
152     string token(" ");
153     ifstream in("D:/Lab/clab/file/1.txt");
154     ofstream out("D:/Lab/clab/file/2.txt");
155
156     vector<string> vec_SerialTree = readFile(in, token);
157
158     int cur = 0;
159     TreeNode *p_Root = DeserializeTree(cur, vec_SerialTree);
160
161     if(out)
162     {
163         SerializeTree(p_Root, out);
164     }
165
166     DestroyTree(&p_Root);
167
168     return 0;
169 }
时间: 2024-10-13 22:13:29

序列化和反序列化二叉树的相关文章

序列化与反序列化二叉树

2018-06-16 18:53:36 序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程.反序列化顾名思义就是通过信息流对对象进行重建的过程. 一般来说序列化和反序列化有如下的作用: 1.以某种存储形式使自定义对象持久化: 2.将对象从一个地方传递到另一个地方. 3.使程序更具维护性. 本篇文章主要讨论的是二叉树的序列化和反序列化,分别讨论了普通二叉树和二叉搜索树的情况. 一.普通二叉树的序列化和反序列化 问题描述: 问题求解: 序列化和反序列化二叉树本质上

[leetcode]297. Serialize and Deserialize Binary Tree 序列化与反序列化二叉树

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another comput

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

import java.util.LinkedList; import java.util.Queue; public class Solution { String Serialize(TreeNode root) { StringBuilder sb = new StringBuilder(); if(root==null) { sb.append("#,"); return sb.toString(); } sb.append(String.valueOf(root.val));

lintcode 中等题:binary tree serialization 二叉树的序列化和反序列化

题目 二叉树的序列化和反序列化 设计一个算法,并编写代码来序列化和反序列化二叉树.将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”. 如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列化为一个字符串,并且可以将字符串反序列化为原来的树结构. 样例 给出一个测试数据样例, 二叉树{3,9,20,#,#,15,7},表示如下的树结构: 3 / 9 20 / 15 7 我们的数据是进行BFS遍历得到的.当你测试结果wrong answer时,你可以作为输

Lintcode---二叉树的序列化和反序列化

设计一个算法,并编写代码来序列化和反序列化二叉树.将树写入一个文件被称为"序列化",读取文件后重建同样的二叉树被称为"反序列化". 如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列化为一个字符串,并且可以将字符串反序列化为原来的树结构. 注意事项 There is no limit of how you deserialize or serialize a binary tree, LintCode will take your output o

二叉树的序列化和反序列化

http://blog.csdn.net/qq_27703417/article/details/70958692 先序遍历二叉树,如果遇到空节点,就在str的末尾加上"#!","#"表示这个节点为空,节点值不存在,当然你也可以用其他的特殊字符,"!"表示一个值的结束.如果遇到不为空的节点,假设节点值为3,就在str的末尾加上"3!".现在请你实现树的先序序列化. 先序遍历 import java.util.*; //使用递归

二叉树的序列化与反序列化

一个二叉树被序列化为数组,如何反序列化,也就是如何从序列化好的一个数组恢复成二叉树? 在上一篇文章中讲述了如何将一个有序数组创建成一个二叉搜索树,那么如果将将一个儿茶搜索树序列化为一个有序数组,然后按照上面的方法在反序列化即可.对二叉搜索树进行中序遍历即可得到一个有序的数组,那么上篇文章已经完成了对二叉搜索树的序列化和反序列化.同时如果想将二叉搜索树的序列化和反序列化的结果通过文件读取,也是同样的道理. 设计一个算法,将一棵二叉搜索树(Binary Search Tree,BST)保存到文件中,

Leetcode 297.二叉树的序列化和反序列化

二叉树地序列化和反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据. 请设计一个算法来实现二叉树的序列化与反序列化.这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构. 示例:  你可以将以下二叉树: 序列化为 "[1,2,3,null,null,4,5]" 提示: 这与 Le

二叉树的序列化和反序列化(先序,按层序列化),包含递归图

目录 二叉树的序列化与反序列化 按层序列化 使用#!和!的原因: 二叉树的序列化与反序列化 序列化:将对象的状态信息转换为可以存储或传输的形式的过程 二叉树的序列化:就是将二叉树转换成字符串 二叉树的反序列化:通过字符串还原一棵二叉树,返回树的头节点. 先序序列化二叉树 上面这棵树的先序序列化结果为5!3!2!1!#!#!#!4!#!#!8!7!6!#!#!#!10!9!#!#!11!#!#! 从上图中我们可以看出在节点为空的位置使用"#!"来代替,每个节点后的数值都添加一个"