面試題37:序列化二叉樹。實現兩個函式,分別用來序列化和反序列化。
我們可以先把一棵二叉樹序列化成乙個前序遍歷序列和乙個中序遍歷序列,然後在反序列化時通過這兩個序列重構出二叉樹。但該思路有兩個缺點:一是該方法要求二叉樹中沒有值重複的節點;二是只有當兩個序列中所有資料都讀出後才能開始反序列化,如果兩個遍歷序列的資料是從乙個流中讀出來的,那麼可能需要等待較長時間。
實際上,如果二叉樹的序列化是從根節點開始的,那麼相應的反序列化在根節點的數值讀出來的時候就可以開始了,因此,我們可以根據前序遍歷的順序來序列化二叉樹,因為前序遍歷是從根節點開始的。
我們可以用特殊字元如$來表示nullptr,節點間用,隔開,如:
我們以上例分析如何反序列化,第乙個讀出的數字是1,這是根節點的值,之後是左子樹的根節點2,接著讀出4,接著兩個$,表明4是葉子節點,接下來回到值為2的節點,由於下乙個字元是$,說明2的右孩子是nullptr,至此左子樹構建完畢,回到根節點構建右子樹:
#include
#include
using
namespace std;
struct binarytreenode
;binarytreenode*
constructcore
(int
* startpreorder,
int* endpreorder,
int* startinorder,
int* endinorder)
else
}int
* rootinorder = startinorder;
while
(rootinorder < endinorder &&
*rootinorder !=
*startpreorder)
if(rootinorder == endinorder &&
*rootinorder !=
*startpreorder)
int leftlength = rootinorder - startinorder;
// 左子樹長度
int* leftpreorderend = startpreorder + leftlength;
// 左子樹尾邊界
if(leftlength >0)
if(leftlength < endpreorder - startpreorder)
return root;
}binarytreenode*
construct
(int
* preorder,
int* inorder,
int length)
return
constructcore
(preorder, preorder + length -
1, inorder, inorder + length -1)
;}void
serialize
(binarytreenode* proot, ostream &stream)
stream << proot-
>m_nvalue <<
",";
serialize
(proot-
>m_pleft, stream)
;serialize
(proot-
>m_pright, stream);}
bool
readstream
(istream& stream,
int* number)
char buffer[32]
;// 用字串儲存數字
buffer[0]
='\0'
;char ch;
stream >> ch;
// 先讀取乙個字元,讀取到的是數字的第一位或"$"
int i =0;
while
(!stream.
eof(
)&& ch !=
',')
bool isnumeric =
false;if
(i >
0&& buffer[0]
!='$'
)// 讀入的只可能是"$"或數字,當不為"$"時
return isnumeric;
}void
deserialize
(binarytreenode*
* proot, istream& stream)
}void
printfromtoptobottom
(binarytreenode* ptreeroot)
deque
> dequetreenode;
dequetreenode.
push_back
(ptreeroot)
;while
(dequetreenode.
size()
)if(pnode-
>m_pright !=
nullptr)}
}int
main()
;int inorder=
; binarytreenode* proot =
construct
(preorder, inorder,6)
;// 根據前序和中序建立樹,樹中不能有相同值的節點
serialize
(proot, cout)
;// 序列化樹
binarytreenode* pdeserializedtreeroot =
nullptr
;// 反序列化樹的根節點
deserialize
(&pdeserializedtreeroot, cin)
;// 反序列化樹
cout <<
"反序列化樹從上到下列印:"
<< endl;
printfromtoptobottom
(pdeserializedtreeroot)
;// 從上到下列印樹驗證反序列化結果
}
劍指offer 序列化二叉樹
請實現兩個函式,分別用來序列化和反序列化二叉樹。首先得理解題目的意思,序列化就是返回乙個帶有 和逗號的字串。反序列化就是根據帶有 和逗號的字串返回一棵二叉樹。比如對於二叉樹 1 2 3 4 5 6 7來講,序列化的結果是1,2,3,4,7,5,而反序列化的結果則是輸出一棵二叉樹。public cla...
劍指Offer 序列化二叉樹
請實現兩個函式,分別用來序列化和反序列化二叉樹 根據前面的面試題重建二叉樹,我們知道可以從前序遍歷和中序遍歷構造出一棵二叉樹。受此啟發,我們可以先把一棵二叉樹序列化成乙個前序遍歷序列和乙個中序序列的結合,然後再反序列化時通過這兩個序列重構出原二叉樹。但是這個思路有兩個缺點。乙個缺點是該方法要求二叉樹...
劍指offer 序列化二叉樹
請實現兩個函式,分別用來序列化和反序列化二叉樹 首先這道題目是要有兩個問題,第乙個是把一棵二叉樹按照前序遍歷的方式變成乙個字串。第二個是把乙個字串變成乙個二叉樹。對於第乙個問題來說,我們要對這棵樹進行乙個前序遍歷,按照中左右的方式放入列表中,如果節點為空,則插入 最後.join 來實現列表到字串的轉...