前序遍历的方法:
节点的定义为:
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-