題目要求:
/**
* 二叉樹的序列化是指:把一棵二叉樹按照某種遍歷方式的結果以某種格式保存為字符串,
* 從而使得內存中建立起來的二叉樹可以持久保存。序列化可以基於先序、中序、后序、層序的二叉樹遍歷方式來進行修改,
* 序列化的結果是一個字符串,序列化時通過 某種符號表示空節點(#),以 ! 表示一個結點值的結束(value!)
*/
二叉樹的序列化和反序列化,特別有意思的一個題目,最近突然發現用好遞歸真的可以非常優雅的寫好代碼!
那將是我畢生追求的目標!---------------->盡管現狀並不盡如人意,可是多磨煉一下自己有什么不好呢?
之所以選這個題目進行整理,是因為二叉樹的序列化和反序列化都用到了遞歸的思想,而且結合了二叉樹的前序遍歷,我覺得非常有意思,為了加強自己的記憶,寫出來
大家一起交流吧!
首先畫一個簡單的樹的模型一起看一下:
首先看序列化部分的代碼:
String Serialize(TreeNode root) { if(root==null) return "#"; return root.val + " "+Serialize(root.left)+" "+Serialize(root.right); }
序列化部分的代碼比較簡單,我們畫一幅樹一下子就可以理解,我覺得樹的前序遍歷過程本身就是一個遞歸的思想,可以回顧一下我們腦子是如何寫一棵樹的前序遍歷的
1--->2-->4-->5--->3-->6-->7 !就是樹的完整的前序遍歷的過程,當我們進到左子樹的時候,本身也是將上一個的程序壓如腦棧!然后左子樹根節點為根節點,繼續遵循中左右的原則進行排序吧!
所以序列化的代碼其實很簡單:
1先是遞歸結束的條件 ---> if(root==null) 那么就return"#";
2 如果根節點不是null的話,那么就遵循着前序遍歷的條件輸出 root.val+" "+Serialize(root.left)+" "+Serialize(root.right); !!!跟人寫前序遍歷的時候的思維完全一致!
接下來看反序列化的代碼:
String dstr=""; TreeNode Deserialize(String str) { dstr = str; return deserialize(); } private TreeNode deserialize() { int index = dstr.indexOf(" "); String Node = index==-1?dstr:dstr.substring(0,index); dstr = index==-1?"":dstr.substring(index+1); if(Node.equals("#"))//一定要注意字符串的相等用equals來判斷不能用== return null; int value = Integer.parseInt(Node); TreeNode t = new TreeNode(value); t.left = deserialize(); t.right = deserialize(); return t; }
反序列化的代碼也用到了遞歸的思想,上面那棵樹,我們寫一下它的序列化的結構是:
1-->2-->4-->#-->#-->5-->#-->#-->3-->6-->#-->#-->7-->#-->#
#號代表的就是null!那么我們來分析一下這個代碼,
首先需要明確 序列化之后的代碼是用" "進行分隔的,所以我們就是要找int index= dstr.indexOf(" ");這樣分成能找到和找不到兩種情況
如果index=-1說明找不到,那么String Node = dstr,找不到說明只有一個Node全部是value,如果找到了就切分substring(0,index)--->index取不到剛好是一個value
然后我們需要將全局的dstr進行切分,也就是說如果你已經把1這個值取出來了,需要切掉!dstr = index==-1?"":dstr.substring(index+1);//從這個空格的下一個字符開始,剛好是下一個value;
之后就是新建TreeNode的節點,然后進行樹的構造過程!
t.left = deserialize();
t.right = deserialize();
return t;
可以發現反序列化真的和序列化產生的字符串配合的十分恰當,讓人 感嘆遞歸的神奇之處!