二叉树的先序、中序、后序遍历
1. 基本规则
- 先序:任何子树的处理顺序都是,先头节点、再左子树、然后右子树
- 中序:任何子树的处理顺序都是,先左子树、再头节点、然后右子树
- 后序:任何子树的处理顺序都是,先左子树、再右子树、然后头节点
2. 递归实现
public static void pre(Node head) {
if (head == null) {
return;
}
System.out.println(head.value);
pre(head.left);
pre(head.right);
}
public static void in(Node head) {
if (head == null) {
return;
}
in(head.left);
System.out.println(head.value);
in(head.right);
}
public static void pos(Node head) {
if (head == null) {
return;
}
pos(head.left);
pos(head.right);
System.out.println(head.value);
}
3. 非递归实现
public static void pre(Node head) {
System.out.print("pre-order: ");
if (head != null) {
Stack<Node> stack = new Stack<Node>();
stack.add(head);
while (!stack.isEmpty()) {
head = stack.pop();
System.out.print(head.value + " ");
if (head.right != null) {
stack.push(head.right);
}
if (head.left != null) {
stack.push(head.left);
}
}
}
System.out.println();
}
public static void in(Node cur) {
System.out.print("in-order: ");
if (cur != null) {
Stack<Node> stack = new Stack<Node>();
while (!stack.isEmpty() || cur != null) {
if (cur != null) {
stack.push(cur);
cur = cur.left;
} else {
cur = stack.pop();
System.out.print(cur.value + " ");
cur = cur.right;
}
}
}
System.out.println();
}
public static void pos1(Node head) {
System.out.print("pos-order: ");
if (head != null) {
Stack<Node> s1 = new Stack<Node>();
Stack<Node> s2 = new Stack<Node>();
s1.push(head);
while (!s1.isEmpty()) {
head = s1.pop(); // 头 右 左
s2.push(head);
if (head.left != null) {
s1.push(head.left);
}
if (head.right != null) {
s1.push(head.right);
}
}
// 左 右 头
while (!s2.isEmpty()) {
System.out.print(s2.pop().value + " ");
}
}
System.out.println();
}
将 N 叉树编码为二叉树
class Codec {
// Encodes an n-ary tree to a binary tree.
public TreeNode encode(Node root) {
if (root == null) {
return null;
}
TreeNode head = new TreeNode(root.val);
head.left = en(root.children);
return head;
}
// 把孩子都通过right指针连接
private TreeNode en(List<Node> children) {
TreeNode head = null;
TreeNode cur = null;
for (Node child : children) {
TreeNode tNode = new TreeNode(child.val); // 生成二叉树节点
if (head == null) { // 只会执行一次
head = tNode;
} else {
cur.right = tNode;
}
cur = tNode; // cur来到新节点
cur.left = en(child.children); // 再递归生成新节点的孩子
}
return head;
}
// Decodes your binary tree to an n-ary tree.
public Node decode(TreeNode root) {
if (root == null) {
return null;
}
return new Node(root.val, de(root.left));
}
// 从第一个兄弟节点开始,构建所有的孩子
public List<Node> de(TreeNode root) {
List<Node> children = new ArrayList<>();
while (root != null) {
Node cur = new Node(root.val, de(root.left)); // 每个兄弟都递归生成孩子
children.add(cur);
root = root.right; // 一直向右,遍历所有兄弟
}
return children;
}
}
求二叉树最宽的层有多少个节点
public static int maxWidthNoMap(Node head) {
if (head == null) {
return 0;
}
Queue<Node> queue = new LinkedList<>();
queue.add(head);
Node curEnd = head; // 当前层,最右节点是谁
Node nextEnd = null; // 下一层,最右节点是谁
int max = 0;
int curLevelNodes = 0; // 当前层的节点数
while (!queue.isEmpty()) {
Node cur = queue.poll();
if (cur.left != null) {
queue.add(cur.left);
nextEnd = cur.left; // 提前记录下一层的最右侧节点
}
if (cur.right != null) {
queue.add(cur.right);
nextEnd = cur.right; // 提前记录下一层的最右侧节点
}
curLevelNodes++;
if (cur == curEnd) { // 如果遍历到的节点是当前层最后一个
max = Math.max(max, curLevelNodes); // 结算当前层节点数
curLevelNodes = 0; // 清零,准备计算下一层
curEnd = nextEnd;
}
}
return max;
}
后继节点
二叉树结构如下定义:
class lass Node {
V value;
Node left;
Node right;
Node parent;
}
给你二叉树中的某个节点,返回该节点的后继节点(中序遍历的下一个节点)
public static Node getSuccessorNode(Node node) {
if (node == null) {
return node;
}
if (node.right != null) { // 其一,右树最左的节点
return getLeftMost(node.right);
} else { // 其二,无右树,如果某个节点左树最右是node,那么此节点就是后继节点
Node parent = node.parent;
while (parent != null && parent.right == node) { // 当前节点是其父亲节点右孩子
node = parent;
parent = node.parent;
}
return parent;
}
}
public static Node getLeftMost(Node node) {
if (node == null) {
return node;
}
while (node.left != null) {
node = node.left;
}
return node;
}