2021/3/4 二叉树的序列化和反序列化(leetcode 297)(程序员代码面试指南p108)(剑指面试题37)

63 篇文章 0 订阅
1 篇文章 0 订阅

前序遍历的方法:
节点的定义为:

	public static class Node {
		public int value;
		public Node left;
		public Node right;

		public Node(int data) {
			this.value = data;
		}
	}

前序的序列化为

	public static String serialByPre(Node head) {
		if (head == null) {
			return "#!";
		}
		String res = head.value + "!";
		res += serialByPre(head.left);
		res += serialByPre(head.right);
		return res;
	}

前序的反序列化为:

	public static Node reconByPreString(String preStr) {
		String[] values = preStr.split("!");
		//将原字符串以“!”分割
		Queue<String> queue = new LinkedList<String>();
		//将处理过的字符串加入队列中,方便后续处理
		for (int i = 0; i != values.length; i++) {
			queue.offer(values[i]);
		}
		return reconPreOrder(queue);
	}
    //由队列建出整个树
	public static Node reconPreOrder(Queue<String> queue) {
		String value = queue.poll();
		if (value.equals("#")) {
			return null;
		}
		Node head = new Node(Integer.valueOf(value));
		//如果不等于#,则头结点消费这个value,建立一个新的node(建立新节点等于head)
		//因为序列化的时候是先中再左再右,所以建立的时候也先中再左再右
		head.left = reconPreOrder(queue);
		//整棵左子树交给递归过程去消费队列
		head.right = reconPreOrder(queue);
		return head;
	}

应该自己画递归图加强理解
在这里插入图片描述
突然发现eclipse看递归好清楚 而且那个以某一个符号分割(split函数)c++也没有
eclipse按F11开始调试 F6一步一步看
完整代码:

package hellojava;
//

//package basic_class_01;


//package class_04;

import java.util.LinkedList;
import java.util.Queue;

public class hellojava {

	public static class Node {
		public int value;
		public Node left;
		public Node right;

		public Node(int data) {
			this.value = data;
		}
	}

	public static String serialByPre(Node head) {
		if (head == null) {
			return "#!";
		}
		String res = head.value + "!";
		res += serialByPre(head.left);
		res += serialByPre(head.right);
		return res;
	}

	public static Node reconByPreString(String preStr) {
		String[] values = preStr.split("!");
		Queue<String> queue = new LinkedList<String>();
		for (int i = 0; i != values.length; i++) {
			queue.offer(values[i]);
		}
		return reconPreOrder(queue);
	}

	public static Node reconPreOrder(Queue<String> queue) {
		String value = queue.poll();
		if (value.equals("#")) {
			return null;
		}
		Node head = new Node(Integer.valueOf(value));
		head.left = reconPreOrder(queue);
		head.right = reconPreOrder(queue);
		return head;
	}

	public static Node generateNodeByString(String val) {
		if (val.equals("#")) {
			return null;
		}
		return new Node(Integer.valueOf(val));
	}

	// for test -- print tree
	public static void printTree(Node head) {
		System.out.println("Binary Tree:");
		printInOrder(head, 0, "H", 17);
		System.out.println();
	}

	public static void printInOrder(Node head, int height, String to, int len) {
		if (head == null) {
			return;
		}
		printInOrder(head.right, height + 1, "v", len);
		String val = to + head.value + to;
		int lenM = val.length();
		int lenL = (len - lenM) / 2;
		int lenR = len - lenM - lenL;
		val = getSpace(lenL) + val + getSpace(lenR);
		System.out.println(getSpace(height * len) + val);
		printInOrder(head.left, height + 1, "^", len);
	}

	public static String getSpace(int num) {
		String space = " ";
		StringBuffer buf = new StringBuffer("");
		for (int i = 0; i < num; i++) {
			buf.append(space);
		}
		return buf.toString();
	}

	public static void main(String[] args) {
		Node head = null;
		printTree(head);

		String pre = serialByPre(head);
		System.out.println("serialize tree by pre-order: " + pre);
		head = reconByPreString(pre);
		System.out.print("reconstruct tree by pre-order, ");
		printTree(head);

		System.out.println("====================================");

		head = new Node(1);
		printTree(head);

		pre = serialByPre(head);
		System.out.println("serialize tree by pre-order: " + pre);
		head = reconByPreString(pre);
		System.out.print("reconstruct tree by pre-order, ");
		printTree(head);

		head = new Node(1);
		head.left = new Node(2);
		head.right = new Node(3);
		head.left.left = new Node(4);
		head.right.right = new Node(5);
		printTree(head);

		pre = serialByPre(head);
		System.out.println("serialize tree by pre-order: " + pre);
		head = reconByPreString(pre);
		System.out.print("reconstruct tree by pre-order, ");
		printTree(head);

		System.out.println("====================================");

		head = new Node(100);
		head.left = new Node(21);
		head.left.left = new Node(37);
		head.right = new Node(-42);
		head.right.left = new Node(0);
		head.right.right = new Node(666);
		printTree(head);

		pre = serialByPre(head);
		System.out.println("serialize tree by pre-order: " + pre);
		head = reconByPreString(pre);
		System.out.print("reconstruct tree by pre-order, ");
		printTree(head);

		System.out.println("====================================");

	}
}


(DFS递归)c++代码为:
参考链接

https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/solution/shou-hui-tu-jie-gei-chu-dfshe-bfsliang-chong-jie-f/

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Codec {

public:
	// Encodes a tree to a single string.
	static string serialize(TreeNode* root) {
		if (root == NULL)
			return "X,";
		string leftNode = serialize(root->left);
		string rightNode = serialize(root->right);
		return to_string(root->val) + "," + leftNode + rightNode;
	}

	// Decodes your encoded data to tree.
	static TreeNode* deserialize(string data) {
		list<string> list = split(data, ',');
		TreeNode* res = buildTree(list);
		return res;
	}

	static TreeNode* buildTree(list<string> &strList)
	{		
		string strtmp = strList.front();
		strList.pop_front();
		if (strtmp == "X")
			return NULL;
		TreeNode* node = new TreeNode(stoi(strtmp));
		node->left = buildTree(strList);
		node->right = buildTree(strList);
		return node;
	}

	static list<string> split(string& str, char c)
	{
		list<string> res;
		for (int lastpos = -1, pos = 0; pos < str.length(); pos++)
		{
			if (str[pos] == c)
			{
				res.push_back(str.substr(++lastpos, pos - lastpos));
				lastpos = pos;
			}
		}
		return res;
	}

};
// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));
  • list是一个线性双向链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内存空间中,并且由指针将有序的元素链接起来。由于其结构的原因,list随机检索的性能非常的不好,因为它不像vector那样直接找到元素的地址,而是要从头一个一个的顺序查找,这样目标元素越靠后,它的检索时间就越长。检索时间与目标元素的位置成正比。虽然随机检索的速度不够快,但是它可以迅速地在任何节点进行插入和删除操作。因为list的每个节点保存着它在链表中的位置,插入或删除一个元素仅对最多三个元素有所影响,不像vector会对操作点之后的所有元素的存储地址都有所影响,这一点是vector 不可比拟的。
  • substr(size_type _Off = 0,size_type _Count = npos)
    一种构造string的方法
    形式 : s.substr(pos, len)
    返回值: string,包含s中从pos开始的len个字符的拷贝(pos的默认值是0,len的默认值是s.size() - pos,即不加参数会默认拷贝整个s)
    异常 :若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾

有一个BFS和DFS的答案 现在暂时不太看得懂

https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/solution/zhong-gui-zhong-ju-shu-de-dfsbfsbian-li-by-jyj407/

剑指上也有 输入数据不一样 还是看不懂

https://github.com/zhedahht/CodingInterviewChinese2/blob/master/37_SerializeBinaryTrees/SerializeBinaryTrees.cpp

-TBC-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值