二叉树的反序列化
通过一个字符串来实现构造一棵二叉树, 方便在leetcode刷题时进行本地调试
例题
实现方案
代码逻辑:
- 将字符串中的数据提取出来, 存放到
vector
容器中 - 使用索引
i
来控制遍历容器中的数据 - 使用
queue
来辅助层次遍历, 每次在加入队列的时候创建节点, 在弹出队列的时候为该节点的left指针
和right指针
赋值
注意事项:
vector
中会保存"null"字符串, 但是queue
中只保存非"null"对应的节点- 在
queue
每次弹出节点时, 索引i
指向的为当前节点的左子节点对应的字符串, 可能为"null". 在执行i++
之后便会对应到当前节点的右子节点. - 经过两次
i++
后, 索引i
对应的正好是下一个弹出节点的左子节点 - 给出的字符串可能省略了最后的一堆连续的"null", 所以使用
if(i < vec_string.size())
进行判断
C++版本
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
TreeNode *deserialize(const vector<string> &vec_string) {
const string FLAG = "null";
/**
* 队列中保存的值都是非null节点
*/
queue<TreeNode *> queue;
TreeNode *root = new TreeNode(stoi(vec_string[0]));
queue.push(root);
int i = 1;
while (!queue.empty()) {
int size = queue.size();
while (size--) {
TreeNode *peek = queue.front();
queue.pop();
if (i < vec_string.size()) {
//左子节点
if (vec_string[i] != FLAG) {
queue.push(new TreeNode(stoi(vec_string[i])));
peek->left = queue.back();
}
i++;
}
if (i < vec_string.size()) {
//由于上面i++,因此此时指向右子节点
if (vec_string[i] != FLAG) {
queue.push(new TreeNode(stoi(vec_string[i])));
peek->right = queue.back();
}
i++;
}
}
}
return root;
}
TreeNode *deserialize(string data) {
vector<string> vec_string;
string word;
for (int i = 0; i <= data.size(); i++) {
if (i == data.size() || data[i] == ',') {
vec_string.push_back(word);
word.clear();
} else {
word += data[i];
}
}
return deserialize(vec_string);
}
Java版本
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
/**
* 二叉树
*
*/
public class BinaryTree implements Order {
//测试案例
public static void main(String[] args) {
String s = "1,2,#,#,3";
BinaryTree binaryTree = new BinaryTree(s);
binaryTree.preOrder();
}
/**
* 二叉树的节点, 内部类
*/
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {
}
public Node(int val) {
this.val = val;
}
public Node(int val, Node left, Node right, Node next) {
this.val = val;
this.left = left;
this.right = right;
this.next = next;
}
}
Node root;
public BinaryTree(String data) {
this.root = deserialize(data);
}
private Node deserialize(ArrayList<String> words) {
final String FLAG = "#";
Deque<Node> queue = new LinkedList<>();
Node root = new Node(Integer.parseInt(words.get(0)));
queue.add(root);
int i = 1;
while (!queue.isEmpty()) {
int size = queue.size();
while (size-- > 0) {
Node peek = queue.peek();
assert peek != null;
queue.poll();
if (i < words.size()) {
//左子节点
if (!words.get(i).equals(FLAG)) {
queue.add(new Node(Integer.parseInt(words.get(i))));
peek.left = queue.getLast();
}
i++;
}
if (i < words.size()) {
//由于上面i++,因此此时指向右子节点
if (!words.get(i).equals(FLAG)) {
queue.add(new Node(Integer.parseInt(words.get(i))));
peek.right = queue.getLast();
}
i++;
}
}
}
return root;
}
private Node deserialize(String data) {
ArrayList<String> words = new ArrayList<>();
StringBuilder word = new StringBuilder();
for (int i = 0; i <= data.length(); i++) {
if (i == data.length() || data.charAt(i) == ',') {
words.add(word.toString());
word = new StringBuilder();
} else {
word.append(data.charAt(i));
}
}
return deserialize(words);
}
private void preOrder(Node root) {
if (root == null) {
return;
}
System.out.println(root.val);
preOrder(root.left);
preOrder(root.right);
}
}