算法 - 二叉树
二叉树
二叉树按层遍历打印
宽度优先遍历,通常使用队列结构。常常有按照层数换行的问题。
1
/ \
2 3
/ / \
4 5 6
/ \
7 8
output:
1
2 3
4 5 6
7 8
思路:
这时可以使用两个变量记录,一个是用变量 last 记录当前的 last 结点,另一个是用变量 nlast 记录下一层的 last 结点。
pop() 时添加子树,如果 pop 值等于 last 指向的变量,打印换行符号,last 变量指向 nlast。
nlast 跟踪的是最新加入 queue 的数。
实现:
public void printTree(TreeNode root) {
TreeNode last = null;
TreeNode nlast = null;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
last = root;
nlast = root;
while (!queue.isEmpty()) {
TreeNode tmp = queue.poll();
System.out.print(tmp.val + " ");
if (tmp.left != null) {
queue.offer(tmp.left);
nlast = tmp.left;
}
if (tmp.right != null) {
queue.offer(tmp.right);
nlast = tmp.right;
}
if (tmp == last) {
last = nlast;
System.out.println();
}
}
}
测试:
public static void main(String[] args) {
// 构建二叉树
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.right.left = new TreeNode(5);
root.right.right = new TreeNode(6);
root.right.left.left = new TreeNode(7);
root.right.left.right = new TreeNode(8);
PrintBinaryTree test = new PrintBinaryTree();
test.printTree(root);
}
二叉树的序列化和反序列化
方式:先序遍历,中序遍历,后序遍历,层序遍历。
给定一个二叉树的头节点 head,节点值的类型是 32 位整型。设计序列化和反序列化方案。
使用树的前序遍历实现序列化:
public static String serializedBinaryTree(TreeNode root) {
StringBuilder sb = new StringBuilder();
preOrderTraversal(root, sb);
return sb.toString();
}
private static void preOrderTraversal(TreeNode node, StringBuilder sb) {
if (node == null) {
sb.append("#!");
return;
}
sb.append(node.val).append("!");
preOrderTraversal(node.left, sb);
preOrderTraversal(node.right, sb);
}
测试:
public static void main(String[] args) {
// 构建二叉树
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.right.left = new TreeNode(5);
root.right.right = new TreeNode(6);
root.right.left.left = new TreeNode(7);
root.right.left.right = new TreeNode(8);
System.out.println(serializedBinaryTree(root));
}
输出结果:
output:
1!2!4!#!#!#!3!5!7!#!#!8!#!#!6!#!#!
其中 # 表示节点为空,! 是分隔符。
实现反序列化:
public static TreeNode deSerializedBinaryTree(String tree) {
String[] s = tree.split("!");
Queue<TreeNode> queue = new LinkedList<>();
for (int i = 0; i < s.length; i++) {
TreeNode node = null;
if (s[i].equals("#")) {
node = new TreeNode(Integer.MIN_VALUE);
} else {
node = new TreeNode(Integer.parseInt(s[i]));
}
queue.offer(node);
}
TreeNode root = queue.poll();
makeTree(root, queue);
return root;
}
private static void makeTree(TreeNode root, Queue<TreeNode> queue) {
if (root == null || root.val == Integer.MIN_VALUE) {
return;
}
root.left = queue.poll();
makeTree(root.left, queue);
root.right = queue.poll();
makeTree(root.right, queue);
}
测试,借用了此前实现序列化的树反序列化:
public static void main(String[] args) {
// 构建二叉树
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.right.left = new TreeNode(5);
root.right.right = new TreeNode(6);
root.right.left.left = new TreeNode(7);
root.right.left.right = new TreeNode(8);
System.out.println(serializedBinaryTree(root));
String s = serializedBinaryTree(root);
TreeNode tree = deSerializedBinaryTree(s);
printTree(tree);
}
输出,借用了此前二叉树按层遍历打印的方法,其中空节点用整型的最小值代替:
1
/ \
2 3
/ / \
4 5 6
/ \
7 8
output:
1
2 3
4 -2147483648 5 6
-2147483648 -2147483648 7 8 -2147483648 -2147483648
-2147483648 -2147483648 -2147483648 -2147483648