序列化二叉樹和反序列化二叉樹


二叉樹被記錄成文件的過程叫作二叉樹的序列化,通過文件內容重建原來的二叉樹過程叫做二叉樹反序列化,

廢話不多說我們來做這兩個功能,首先給定一顆二叉樹的節點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         }

輸出了正確的結果


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM