您的位置:首页 > 其它

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

2016-07-25 21:53 260 查看
原文链接:http://www.cnblogs.com/PrimeLife/p/5504379.html

【说明】:

  本文是左程云老师所著的《程序员面试代码指南》第三章中“二叉树的序列化和反序列化”这一题目的C++复现。

  本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。

  感谢左程云老师的支持。

【题目】:

  二叉树被记录成文件的过程叫作二叉树的序列化,通过文件内容重建原来二叉树的过程叫做二叉树的反序列化。给定一颗二叉树的头节点 head,并已知二叉树节点值的类型为32位整形。请设计一种二叉树序列化和反序列化的方案,并用代码实现。

 【思路】:

  解法为先序遍历和层遍历两种。

【编译环境】:

  CentOS6.7(x86_64)

  gcc 4.4.7

 【实现及测试】:

  声明代码:

/*
*文件名:bt_serial.h
*作者:
*摘要:实现二叉树的序列化和反序列化
*/

#include <string>

using namespace std;

class Node
{
public:
Node(int data)
{
value = data;
left = NULL;
right = NULL;
}
public:
int value;
Node *left;
Node *right;
};

string serialByPre(Node *root); //通过先序遍历序列化为字符串
Node* reconByPreString(string preStr); //将通过先序遍历序列化得到的的字符串反序列化

string serialByLevel(Node *root);    //按层遍历序列化
Node* reconByLevelString(string levelStr);//根据层遍历反序列化
View Code

  实现及测试代码:

/*
*文件名:bt_serial.cpp
*作者:
*摘要:二叉树序列化与反序列化的实现
*/

#include "bt_serial.h"
#include <queue>
#include <sstream>
#include <iostream>

//字符串转换为整形
int strToint(string &svalue)
{
stringstream ss;
ss << svalue;
int ivalue;
ss >> ivalue;
return ivalue;
}

//整形转换为字符串
string intTostr(int &ivalue)
{
stringstream ss;
ss << ivalue;
string svalue;
ss >> svalue;
return svalue;
}

string serialByPre(Node *root)
{
if(NULL == root)
return "#!";

string svalue = intTostr(root->value);

string res = svalue + "!";
res += serialByPre(root->left);
res += serialByPre(root->right);
return res;
}

Node* reconPreOrder(queue<string> *q)
{
string svalue = q->front();
q->pop();
//    cout << svalue << endl;
if("#" == svalue)
return NULL;

int ivalue = strToint(svalue);

Node *root = new Node(ivalue);
root->left=reconPreOrder(q);
root->right=reconPreOrder(q);
return root;
}

Node* reconByPreString(string preStr)
{
size_t firPos = 0;
size_t secPos = 0;
queue<string>* q = new queue<string>;   //注意指针的使用

secPos = preStr.find("!");
while(secPos != string::npos)
{
q->push(preStr.substr(firPos, secPos - firPos));
firPos = secPos + 1;
secPos = preStr.find("!", firPos);
}

return reconPreOrder(q);
}

string serialByLevel(Node* root)
{
if(NULL == root)
return "#!";

string svalue = intTostr(root->value);

string res = svalue + "!";
queue<Node*> q;
q.push(root);

while(!q.empty())
{
root = q.front();
q.pop();

if(NULL != root->left)
{
svalue = intTostr(root->left->value);
res += svalue + "!";
q.push(root->left);
}
else
{
res += "#!";
}

if(NULL != root->right)
{
svalue = intTostr(root->right->value);
res += svalue + "!";
q.push(root->right);
}
else
{
res += "#!";
}
}
return res;
}

Node* generateNodeByString(string val)
{
if("#" == val)
return NULL;

return new Node(strToint(val));
}

Node* reconByLevelString(string levelStr)
{
size_t firPos = 0;
size_t secPos = levelStr.find("!");
queue<string>* qStr = new queue<string>;   //注意指针的使用

while(secPos != string::npos)
{
qStr->push(levelStr.substr(firPos, secPos - firPos));
//    cout << qStr->back() << endl;
firPos = secPos + 1;
secPos = levelStr.find("!", firPos);
}

queue<Node*>* qNode = new queue<Node*>;   //注意指针的使用
Node *root = generateNodeByString(qStr->front());
qStr->pop();
if (NULL != root)
qNode->push(root);

Node *node = NULL;
while(!qNode->empty())
{
node = qNode->front();
qNode->pop();

if (NULL != node)
cout << node->value << endl;
else
cout << "#" << endl;

node->left = generateNodeByString(qStr->front());
qStr->pop();
node->right = generateNodeByString(qStr->front());
qStr->pop();
if(NULL != node->left)
qNode->push(node->left);
if(NULL != node->right)
qNode->push(node->right);
}
return root;
}

int main()
{
string str = "12!3!#!#!#!";
Node *root = reconByPreString(str);
string str1 = serialByPre(root);
cout << str1 << endl;

root = reconByLevelString(str);
str1 = serialByLevel(root);
cout << str1 << endl;
return 0;
}
View Code

说明:

  由JAVA代码转到C++代码,像字符串类、队列类的在使用上的差距比较大。但是整体的思路还是左老师在书中所提出的。

  

注:

  转载请注明出处;

  转载请注明源思路来自于左程云老师的《程序员代码面试指南》。

转载于:https://www.cnblogs.com/PrimeLife/p/5504379.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: