为什么要有二叉树的序列化和反序列化,因为我们构造的二叉树,都是存放在计算机的内存中,但是我们想要根据记录重新构造出二叉树就需要二叉树的序列化和反序列化,将二叉树以文件的方式存下来叫做二叉树的序列化,从文件构造出二叉树叫做二叉树的反序列化。
这里说明一下满二叉树和完全二叉树的区别:满二叉树(如下图)可以说是一个非常标准的三角形,除了最后一层叶子节点外,其他每个节点都是度为2的节点,满足节点数=(2^k)-1,k为二叉树的层数。
完全二叉树:看了好多种定义大体是一致的。完全二叉树和满二叉树的差别在最后一层,最后一层节点可以是满的,也可以是一个,但是缺少的总是右面的,所以满二叉树也是完全二叉树
首先构造一个二叉树,进行中序遍历,每个节点结束用!标记,如果为空节点用#标记。遍历之后得到一个字符串
private TreeNode root = null; private static Queue<String> q = null; public BinTree1() { root = new TreeNode("A"); } public void createBinTree(TreeNode root) { TreeNode Bnode = new TreeNode("B"); TreeNode Cnode = new TreeNode("C"); TreeNode Dnode = new TreeNode("D"); TreeNode Enode = new TreeNode("E"); TreeNode Fnode = new TreeNode("F"); TreeNode Gnode = new TreeNode("G"); root.leftChild = Bnode; root.rightChild = Cnode; root.leftChild.leftChild = Dnode; root.leftChild.rightChild = Enode; root.rightChild.leftChild = Fnode; root.rightChild.rightChild = Gnode; } public void preOrder(TreeNode node) { if (node != null) { preOrder(node.leftChild); visited(node); preOrder(node.rightChild); } if (node == null) { System.out.print("#!"); } } public static void visited(TreeNode node) { System.out.print(node.data + "!"); }
得到 #!D!#!B!#!E!#!A!#!F!#!C!#!G!#!
接下来我们用先序遍历得到的字符串A!B!D!#!#!E!#!#!C!F!#!#!G!#!#!进行反序列化测试
public TreeNode create(String str){ q=new LinkedList<String>(); String[] nodes=str.split("!"); for(int i=0;i<nodes.length;i++){ q.offer(nodes[i]); } TreeNode node=pre(q); return node; } public TreeNode pre(Queue<String> q){ String s=q.poll(); if("#".equals(s)){ return null; } TreeNode node=new TreeNode(s); node.leftChild=pre(q); node.rightChild=pre(q); return node; }
以上方法用到一个辅助队列,先用一个方法把得到的字符串拆分成节点数组,之后存入队列中。什么方式序列化就用什么方式进行反序列化,一定要注意这点,否则重构不出二叉树,重构出来的二叉树一定是唯一的,先序遍历得到的序列化的内容,就要用先序的方式去反序列化。
完整代码:
package demo_datastruct; import java.util.LinkedList; import java.util.Queue; /** * 二叉树的序列化和反序列化 * * @author asus * */ public class BinTree1 { private TreeNode root = null; private static Queue<String> q = null; public BinTree1() { root = new TreeNode("A"); } public static void main(String[] args) { BinTree1 bin = new BinTree1(); String str = "A!B!D!#!#!E!#!#!C!F!#!#!G!#!#!"; TreeNode f=bin.create(str); bin.preOrder(f); } public void createBinTree(TreeNode root) { TreeNode Bnode = new TreeNode("B"); TreeNode Cnode = new TreeNode("C"); TreeNode Dnode = new TreeNode("D"); TreeNode Enode = new TreeNode("E"); TreeNode Fnode = new TreeNode("F"); TreeNode Gnode = new TreeNode("G"); root.leftChild = Bnode; root.rightChild = Cnode; root.leftChild.leftChild = Dnode; root.leftChild.rightChild = Enode; root.rightChild.leftChild = Fnode; root.rightChild.rightChild = Gnode; } public void preOrder(TreeNode node) { if (node != null) { preOrder(node.leftChild); visited(node); preOrder(node.rightChild); } if (node == null) { System.out.print("#!"); } } public static void visited(TreeNode node) { System.out.print(node.data + "!"); } public TreeNode create(String str){ q=new LinkedList<String>(); String[] nodes=str.split("!"); for(int i=0;i<nodes.length;i++){ q.offer(nodes[i]); } TreeNode node=pre(q); return node; } public TreeNode pre(Queue<String> q){ String s=q.poll(); if("#".equals(s)){ return null; } TreeNode node=new TreeNode(s); node.leftChild=pre(q); node.rightChild=pre(q); return node; } }
最后用中序又遍历一下得到
#!D!#!B!#!E!#!A!#!F!#!C!#!G!#!