二叉树被记录成文件的过程叫作二叉树的序列化,通过文件内容重建原来的二叉树过程叫做二叉树反序列化,
废话不多说我们来做这两个功能,首先给定一颗二叉树的节点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 }