这是一个相当考察数据结构基础知识的题目。二叉树序列化本身很简单,中序遍历递归一遍就可以存储了。但是问题是要能反序列化成功,就必须把树形结构本身的信息保存下来。因为保存程序不能事先知道序列化以后左边和右边的树分别有多大,所以必须采用先序遍历,
(1) 先保存当前子树的树根,节点的信息不再是指针,而是偏移量。如果没有左子树,则左偏移量为0。
(2) 如果有左子树,则递归序列化保存左子树,保存的过程的递归函数要返回已经保存的节点的数量。等待左子树递归完成,得到了左子树的大小。
(3) 如果有右子树,那么当前子树树根节点的右子树开始存储的偏移量就是刚才保存的左子树大小。寻址到这个位置,开始递归保存右子树。C++实现代码如下(VC2012测试):
- #include"stdafx.h"
- #include<algorithm>
- #include<iostream>
- #include<string>
- #include<cstdio>
- #include<deque>
- using namespace std;
- template<template<class U> class TFunc,class T>
- struct treeNode{
- int value;
- treeNode* pLeft;
- treeNode* pRight;
- treeNode(int v){
- value=v;
- pLeft=nullptr;
- pRight=nullptr;
- }
- ~treeNode(){
- if(pLeft)delete pLeft;
- if(pRight)delete pRight;
- }
- void AddNodeImpl(const T& v){
- if(TFunc<T>()(v,value)){
- if(pLeft==nullptr){
- pLeft=new treeNode(v);
- }else{
- pLeft->AddNodeImpl(v);
- }
- }else{
- if(pRight==nullptr){
- pRight=new treeNode(v);
- }else{
- pRight->AddNodeImpl(v);
- }
- }
- }
- void printImpl(){
- if(pLeft) pLeft->printImpl();
- printf("%d,",value);
- if(pRight)pRight->printImpl();
- }
- };
- template<template<class U> class TFunc,class T>
- class Tree{//排序树,按升序
- public:
- typedef treeNode<TFunc,T> nodeType;
- Tree(){m_pRoot=nullptr;}
- ~Tree(){
- if(m_pRoot){
- delete m_pRoot;
- m_pRoot=nullptr;
- }
- }
- void AddNode(const T& value){
- if(m_pRoot!=nullptr){
- m_pRoot->AddNodeImpl(value);
- }else{//空树
- m_pRoot=new nodeType(value);
- return;
- }
- }
- void print(){
- if(m_pRoot)m_pRoot->printImpl();
- printf("\n");
- }
- struct streamNode{
- T value;
- size_t LOffset;//左节点偏移,只取0或者1. 0代表没有左节点,1代表做节点紧接着存
- size_t ROffset;//右节点偏移,0代表没有右节点
- streamNode(T v,size_t nL,size_t nR):
- value(v),LOffset(nL),ROffset(nR)
- {}
- };
- void streamOut(){
- if(m_pRoot)streamOutImpl(m_pRoot);
- }
- void streamIn(const deque<streamNode>& queue){
- if(queue.empty())return;
- if(m_pRoot)delete m_pRoot;
- const streamNode& n=queue.front();
- streamInImpl(n,queue,0);
- }
- void printStream(){
- for( const streamNode& n : m_queue ){
- printf("%d,%d,%d\n",n.value,n.LOffset,n.ROffset);
- }
- }
- const deque<streamNode>& GetStreamedQueue() const{
- return m_queue;
- }
- private:
- size_t streamOutImpl(const nodeType* pNode){
- size_t nStreamed = 1;
- m_queue.push_back(streamNode(pNode->value,0,0));
- streamNode& n = m_queue.back();
- if(pNode->pLeft){
- n.LOffset=1;
- nStreamed += streamOutImpl(pNode->pLeft);
- }
- if(pNode->pRight){
- n.ROffset=nStreamed;
- nStreamed +=streamOutImpl(pNode->pRight);
- }
- return nStreamed;
- }
- void streamInImpl(const streamNode& n,const deque<streamNode>& queue,const size_t nOff){
- AddNode(n.value);
- if(n.LOffset){
- size_t nTotalOffset=n.LOffset+nOff;
- streamInImpl(queue[nTotalOffset],queue,nTotalOffset);
- }
- if(n.ROffset){
- size_t nTotalOffset=n.ROffset+nOff;
- streamInImpl(queue[nTotalOffset],queue,nTotalOffset);
- }
- };
- nodeType* m_pRoot;
- deque<streamNode> m_queue;
- };
- int main(){
- Tree<less,int> t1,t2;
- t1.AddNode(3);
- t1.AddNode(5);
- t1.AddNode(4);
- t1.AddNode(6);
- t1.AddNode(2);
- t1.AddNode(7);
- t1.print();
- t1.streamOut();
- t1.printStream();
- t2.streamIn(t1.GetStreamedQueue());
- t2.print();
- return 0;
- }
#include"stdafx.h"
#include<algorithm>
#include<iostream>
#include<string>
#include<cstdio>
#include<deque>
using namespace std;
template<template<class U> class TFunc,class T>
struct treeNode{
int value;
treeNode* pLeft;
treeNode* pRight;
treeNode(int v){
value=v;
pLeft=nullptr;
pRight=nullptr;
}
~treeNode(){
if(pLeft)delete pLeft;
if(pRight)delete pRight;
}
void AddNodeImpl(const T& v){
if(TFunc<T>()(v,value)){
if(pLeft==nullptr){
pLeft=new treeNode(v);
}else{
pLeft->AddNodeImpl(v);
}
}else{
if(pRight==nullptr){
pRight=new treeNode(v);
}else{
pRight->AddNodeImpl(v);
}
}
}
void printImpl(){
if(pLeft) pLeft->printImpl();
printf("%d,",value);
if(pRight)pRight->printImpl();
}
};
template<template<class U> class TFunc,class T>
class Tree{//排序树,按升序
public:
typedef treeNode<TFunc,T> nodeType;
Tree(){m_pRoot=nullptr;}
~Tree(){
if(m_pRoot){
delete m_pRoot;
m_pRoot=nullptr;
}
}
void AddNode(const T& value){
if(m_pRoot!=nullptr){
m_pRoot->AddNodeImpl(value);
}else{//空树
m_pRoot=new nodeType(value);
return;
}
}
void print(){
if(m_pRoot)m_pRoot->printImpl();
printf("\n");
}
struct streamNode{
T value;
size_t LOffset;//左节点偏移,只取0或者1. 0代表没有左节点,1代表做节点紧接着存
size_t ROffset;//右节点偏移,0代表没有右节点
streamNode(T v,size_t nL,size_t nR):
value(v),LOffset(nL),ROffset(nR)
{}
};
void streamOut(){
if(m_pRoot)streamOutImpl(m_pRoot);
}
void streamIn(const deque<streamNode>& queue){
if(queue.empty())return;
if(m_pRoot)delete m_pRoot;
const streamNode& n=queue.front();
streamInImpl(n,queue,0);
}
void printStream(){
for( const streamNode& n : m_queue ){
printf("%d,%d,%d\n",n.value,n.LOffset,n.ROffset);
}
}
const deque<streamNode>& GetStreamedQueue() const{
return m_queue;
}
private:
size_t streamOutImpl(const nodeType* pNode){
size_t nStreamed = 1;
m_queue.push_back(streamNode(pNode->value,0,0));
streamNode& n = m_queue.back();
if(pNode->pLeft){
n.LOffset=1;
nStreamed += streamOutImpl(pNode->pLeft);
}
if(pNode->pRight){
n.ROffset=nStreamed;
nStreamed +=streamOutImpl(pNode->pRight);
}
return nStreamed;
}
void streamInImpl(const streamNode& n,const deque<streamNode>& queue,const size_t nOff){
AddNode(n.value);
if(n.LOffset){
size_t nTotalOffset=n.LOffset+nOff;
streamInImpl(queue[nTotalOffset],queue,nTotalOffset);
}
if(n.ROffset){
size_t nTotalOffset=n.ROffset+nOff;
streamInImpl(queue[nTotalOffset],queue,nTotalOffset);
}
};
nodeType* m_pRoot;
deque<streamNode> m_queue;
};
int main(){
Tree<less,int> t1,t2;
t1.AddNode(3);
t1.AddNode(5);
t1.AddNode(4);
t1.AddNode(6);
t1.AddNode(2);
t1.AddNode(7);
t1.print();
t1.streamOut();
t1.printStream();
t2.streamIn(t1.GetStreamedQueue());
t2.print();
return 0;
}
运行结果是:
2,3,4,5,6,7, // 排序二叉树的内容
3,1,2 // t1 开始存根节点
2,0,0 // 序列化其他的节点
5,1,2
4,0,0
6,0,1
7,0,0
2,3,4,5,6,7, // 反序列化的子树 t2