zoukankan      html  css  js  c++  java
  • 序列化和反序列化二叉树

    今天练习算法,在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 }
  • 相关阅读:
    利用git上传到码云
    js 数组的方法总结
    什么是浏览器的回流和重绘以及如何减少回流和重绘
    数组的方法some和includes
    node.js中使用http-proxy-middleware请求转发给其它服务器
    什么是BFC
    如何用Github上传项目中的代码
    前端渲染与后端渲染的区别有哪些
    移动端路由的切换
    面试题
  • 原文地址:https://www.cnblogs.com/flyingpeguin/p/4307112.html
Copyright © 2011-2022 走看看