二叉树序列化和反序列化的3种方式

1. 前序遍历

public class Codec {
    
    

    public String serialize(TreeNode root) {
    
    
        if(root==null) {
    
    
        	return "#";
        }
        return root.val+","+serialize(root.left)+","+serialize(root.right);
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
    
    
        String[] values=data.split(",");
        LinkedList<String> q=new LinkedList<>();
        q.addAll(Arrays.asList(values));
        return deserialize(data, q);
    }
    public TreeNode deserialize(String data,LinkedList<String> q) {
    
    
    	String s=q.removeFirst();
    	if(s.equals("#")) {
    
    
    		return null;
    	}
    	TreeNode node=new TreeNode(Integer.parseInt(s));
    	node.left=deserialize(data, q);
    	node.right=deserialize(data, q);
    	return node;
    }
}

2. 后序遍历

public String serialize(TreeNode root) {
    
    
       if(root==null) {
    
    
        	return "#";
        }
        return serialize(root.left)+","+serialize(root.right)+","+root.val;
    }
   
    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
    
    
        String[] values=data.split(",");
        LinkedList<String> q=new LinkedList<>();
        q.addAll(Arrays.asList(values));
        return deserialize(data, q);
    }
    public TreeNode deserialize(String data,LinkedList<String> q) {
    
    
    	String s=q.removeLast();
    	if(s.equals("#")) {
    
    
    		return null;
    	}
    	TreeNode node=new TreeNode(Integer.parseInt(s));
    	node.right=deserialize(data, q);//左右根 根节点处理完了 往后取的是右结点
    	node.left=deserialize(data, q);
    	return node;
    }

后序处理的方式相较于前序遍历,只需要改变两个地方:

  1. 前序是每次取队列中的第一个元素,后序是取队列中的最后一个元素
  2. 前序反序列化递归顺序是“根左右”, 后续反序列化递归顺序是“根右左”

3. 层次遍历

public String serialize(TreeNode root) {
    
    
		LinkedList<TreeNode> q = new LinkedList<>();
		StringBuilder sb = new StringBuilder();
		q.offer(root);
		while (!q.isEmpty()) {
    
    
			TreeNode node = q.poll();
			if (node == null) {
    
    
				sb.append("#" + ",");
				continue;
			}
			sb.append(node.val + ",");

			q.offer(node.left);//空节点也需要入队 后面作为#拼接

			q.offer(node.right);

		}
		return sb.toString().substring(0, sb.length() - 1);// 最后多了1个逗号 去掉
	}

	// Decodes your encoded data to tree.
	public TreeNode deserialize(String data) {
    
    
		String[] values = data.split(",");
		int n = values.length;
		if (values[0].equals("#")) {
    
    
			return null;
		}
		LinkedList<TreeNode> q = new LinkedList<>();
		q.offer(new TreeNode(Integer.parseInt(values[0])));
		TreeNode root = q.peek();
		int i = 1;// 注意i从1开始 因为根节点不作为子节点
		while (i < n) {
    
    
			TreeNode node = q.poll();// 获取队首节点
			if (!values[i].equals("#")) {
    
    // 当前节点存在左子节点
				node.left = new TreeNode(Integer.parseInt(values[i]));
				q.offer(node.left);// 左子节点加入队列 下一次取出来处理
			}
			i += 1;
			if (!values[i].equals("#")) {
    
    // 当前节点存在右子节点
				node.right = new TreeNode(Integer.parseInt(values[i]));
				q.offer(node.right);
			}
			i += 1;

		}
		return root;
	}
  1. 序列化时使用一个队列,同时拼接字符串
  2. 反序列化时也需要使用一个队列保存已经创建的非空节点,空节点不入队

没有中序序列化方式,中序序列化不能确定一棵二叉树

猜你喜欢

转载自blog.csdn.net/qq_43478694/article/details/126901281