二叉樹被記錄成文件的過程叫作二叉樹的序列化,通過文件內容重建原來的二叉樹過程叫做二叉樹反序列化,
廢話不多說我們來做這兩個功能,首先給定一顆二叉樹的節點head,並已知二叉樹結點的值類型為32位整型,
補充說明:這里是通過先序遍歷來實現序列化和反序列化過程(及先輸出當前節點,再輸出左節點,最后輸出右節點)
序列化的思路:
首先加上序列化的結果字符串為str,初始時 str=" "。先遍歷二叉樹,如果遇到null節點,就在str的末尾加上“#!","#"表示這個節點為空,
節點值不存在,“!”表示一個值結束;如果遇到不為空的節點,假設值為3,就在str的末尾加上“3!"。
用這個數為例子他序列化出來的字符串為:1!2!4!#!7!#!#!#!3!5!#!#!6!#!#!
我們先寫序列化的代碼
1 public class Node 2 { 3 public int value; 4 public Node left; 5 public Node right; 6
7 public Node(int data) 8 { 9 this.value = data; 10 } 11
12 /**************序列化二叉樹和反序列化二叉樹***************/
13 //首先把二叉樹每個數輸出字符串並加上"!" 14 //如果是空數據則返回"#!",然后使用先序來保存數據結構
15
16 /// <summary>
17 /// 序列化先序遍歷二叉樹 18 /// 將二叉樹序列按先序遍歷輸成字符 19 /// </summary>
20 /// <param name="head">結點</param>
21 /// <returns></returns>
22 public string SerialByPre(Node head) 23 { 24 //如果節點沒有數據則結束遞歸,返回 "#!"
25 if (head == null) return "#!"; 26 //將當前節點的數據變成字符 “1!”
27 string res = head.value + "!"; 28 //遞歸遍歷左節點
29 res += SerialByPre(head.left); 30 //遞歸遍歷右節點
31 res += SerialByPre(head.right); 32 //返回字符
33 return res; 34 }
然后繼續完成反序列化的代碼
1 /// <summary>
2 /// 反序列化二叉樹 3 /// </summary>
4 /// <param name="preStr">字符串</param>
5 /// <returns></returns>
6 public Node ReconByPreString(string preStr) 7 { 8 //將序列化的二叉樹元素分別保存到數組
9 string[] values = preStr.Split('!'); 10 //創建隊列
11 Queue<string> queue = new Queue<string>(); 12 //循環將二叉樹元素字符加入隊列中
13 for (int i = 0; i <values.Length; i++) 14 { 15 queue.Enqueue(values[i]); 16 } 17 //創建二叉樹
18 return ReconPreOrder(queue); 19 } 20
21 /// <summary>
22 /// 根據隊列創建二叉樹 23 /// </summary>
24 /// <param name="queue">隊列</param>
25 /// <returns></returns>
26 public Node ReconPreOrder(Queue<string> queue) 27 { 28 //從隊列取出頭元素並刪除
29 string value = queue.Dequeue(); 30 //如果沒數據則退出遞歸
31 if (value.Equals("#")) return null; 32 //創建一個新的結點並給它賦值
33 Node head = new Node(int.Parse(value)); 34 //遞歸得到當前結點的左孩子(遇到“#”則結束)
35 head.left = ReconPreOrder(queue); 36 //遞歸得到當前結點的右孩子(遇到“#”則結束)
37 head.right = ReconPreOrder(queue); 38 //返回這個二叉樹的頭結點
39 return head; 40 }
最后還需要一個先序遍歷函數輸出這個數來驗收結果
1 //先序輸出二叉樹數據結構
2 public void PreOrderUnRecur(Node head) 3 { 4 if (head == null) return; 5 Console.Write(head.value + " "); 6 PreOrderUnRecur(head.left); 7 PreOrderUnRecur(head.right); 8 }
最后我們來調用這序列化和反序列化函數
1 static void Main(string[] args) 2 { 3 Node A = new Node(1); 4 Node B = new Node(2); 5 Node C = new Node(3); 6 Node D = new Node(4); 7 Node E = new Node(5); 8 Node F = new Node(6); 9 Node G = new Node(7); 10
11 A.left = B; 12 A.right = C; 13 B.left = D; 14 D.right = G; 15 C.left = E; 16 C.right = F; 17
18 string res= A.SerialByPre(A); 19 Console.WriteLine(res); 20 Node head=A.ReconByPreString(res); 21 A.PreOrderUnRecur(head); 22 Console.ReadKey(); 23 }