剑指offer:二叉树的序列化和反序列化

来源:互联网 发布:有高跟鞋也有跑鞋 知乎 编辑:程序博客网 时间:2024/06/11 17:22

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

剑指offer上如是说:

我们知道,可以从二叉树的先序序列和中序序列构造一棵二叉树。受此启发,我们可以先把一棵二叉树序列化成一个前序遍历序列和一个中序遍历序列,然后反序列化时通过这两个序列重构二叉树。

上面的思路有一个缺点,上面的思路要求二叉树不能有数值重复的结点。另外只有当两个序列所有数据都读出后才能开始反序列化。如果两个遍历序列的数据是从一个流中读出来的,那就可能需要等较长的时间。

实际上如果二叉树的序列化是从根节点开始的话,那么相应的反序列化在根节点的数值读出来的时候就可以开始了。因此我们可以根据前序遍历的顺序来序列化二叉树,因为前序遍历是从根节点开始的。当在遍历而阐述碰到NULL指针时,这些NULL指针序列化成一个特殊的字符(比如‘$')。另外,节点的数值之间要用一个特殊字符,(比如说’,‘),隔开。

//BinaryTreeNode.h文件

#ifndef __BINARY_TREE_NODE__
#define __BINARY_TREE_NODE__


struct BinaryTreeNode
{
int val;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
BinaryTreeNode();
BinaryTreeNode(int ival);
};

#endif

//BinaryTreeNode.cpp文件

#include <iostream>
#include "BinaryTreeNode.h"
//struct BinaryTreeNode
//{
// int val;
// struct BinaryTreeNode* left;
// struct BinaryTreeNode* right;
// BinaryTreeNode();
// BinaryTreeNode(int ival);
//};
BinaryTreeNode::BinaryTreeNode()
{
val = 0;
left = NULL;
right = NULL;
}


BinaryTreeNode::BinaryTreeNode(int ival) : val(ival), left(NULL), right(NULL)
{
}

//test.cpp

/********************************************
日    期:2016.4.16
作    者:MrWang
函数功能:序列化二叉树及反序列化二叉树


//struct BinaryTreeNode
//{
// int val;
// struct BinaryTreeNode* left;
// struct BinaryTreeNode* right;
// BinaryTreeNode();
// BinaryTreeNode(int ival);
//};
********************************************/
#include <iostream>
#include <sstream>
#include <string>
#include <exception>
#include "BinaryTreeNode.h"
using namespace std;
//建立二叉树,通过指明每一个节点的左右孩子来建立二叉树
void CreatBinaryTree(BinaryTreeNode* &pNode, BinaryTreeNode *pleft, BinaryTreeNode *pright){
if (pNode == NULL)
{
throw new exception("the node is NULL!");
}
pNode->left = pleft;
pNode->right = pright;
return;
}
//树的先序遍历
void preOrder(BinaryTreeNode *pRoot)
{
if (NULL == pRoot)
return;
cout << pRoot->val;
preOrder(pRoot->left);
preOrder(pRoot->right);
return;
}
//Serialize函数用来序列化二叉树
void Serialize(BinaryTreeNode *pRoot, ostream& stream)
{
if (NULL == pRoot)
{
stream << "$,";
return;
}
stream << pRoot->val;
stream << ',';
Serialize(pRoot->left, stream);
Serialize(pRoot->right, stream);
}
//下面反序列化二叉树
//IsDigit用来判断输入的二叉树序列中节点的关键值是数字,还是空
bool IsDigit(istream& stream, int &number)
{
if (stream.eof())
{
return false;
}
char c;
stream >> c;
string str;
if (c == '$')
{
stream >> c;
return false;
}


while (!stream.eof() && c != ','){
str += c;
stream >> c;
}
stringstream strstr;
strstr << str;
strstr >> number;
return true;
}
//reSerialize函数用来反序列化二叉树
void reSerialize(BinaryTreeNode **ppNode, istream& stream)
{
int number;
if (IsDigit(stream, number)){
*ppNode = new BinaryTreeNode(number);
reSerialize(&((*ppNode)->left), stream);
reSerialize(&((*ppNode)->right), stream);
}
return;
}
void releaseNode(BinaryTreeNode *pNode)
{
if (NULL == pNode)
{
return;
}
BinaryTreeNode *pleft = pNode->left;
BinaryTreeNode *pright = pNode->right;
delete pNode;
releaseNode(pleft);
releaseNode(pright);
return;
}
void test1(){
//动态建立六个节点
BinaryTreeNode *pNode1 = new BinaryTreeNode(1);
BinaryTreeNode *pNode2 = new BinaryTreeNode(2);
BinaryTreeNode *pNode3 = new BinaryTreeNode(3);
BinaryTreeNode *pNode4 = new BinaryTreeNode(4);
BinaryTreeNode *pNode5 = new BinaryTreeNode(5);
BinaryTreeNode *pNode6 = new BinaryTreeNode(6);
//通过下面三条语句建立一棵如下的二叉树
// 1
// 2           3
// 4          5   6
CreatBinaryTree(pNode1, pNode2, pNode3);
CreatBinaryTree(pNode2, pNode4, NULL);
CreatBinaryTree(pNode3, pNode5, pNode6);


//序列化二叉树
stringstream strstr;
string str;
Serialize(pNode1, strstr);
strstr >> str;
cout << str << endl;
//反序列化二叉树
strstr.clear();
strstr << str;
BinaryTreeNode *pRoot = NULL;
reSerialize(&pRoot, strstr);
cout << "先序遍历结果:";
preOrder(pRoot);//先序遍历反序列化的二叉树
cout << endl;
releaseNode(pRoot);


delete pNode1;
delete pNode2;
delete pNode3;
delete pNode4;
delete pNode5;
delete pNode6;
}


int main(void)
{
test1();
return 0;
}

0 0
原创粉丝点击