序列化二叉树和反序列化二叉树


二叉树被记录成文件的过程叫作二叉树的序列化,通过文件内容重建原来的二叉树过程叫做二叉树反序列化,

废话不多说我们来做这两个功能,首先给定一颗二叉树的节点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