一、二叉树的遍历
1、递归方式
二叉树的遍历采用递归的方式,每一个节点会回到三次(0:57)
先序遍历指的是先打印头节点,再打印左节点,再打印右节点,先序由递归序加工而来,不是第一次不打印(1:05)
中序遍历指的是先打印左节点,再打印头节点,再打印右节点,不是第二次不打印
后序遍历指的是先打印右节点,再打印左节点,不是第三次不打印
public static void preOrderRecur(Node head) {
if (head == null) {
return;
}
System.out.print(head.value + " ");
preOrderRecur(head.left);
preOrderRecur(head.right);
}
public static void inOrderRecur(Node head) {
if (head == null) {
return;
}
inOrderRecur(head.left);
System.out.print(head.value + " ");
inOrderRecur(head.right);
}
public static void posOrderRecur(Node head) {
if (head == null) {
return;
}
posOrderRecur(head.left);
posOrderRecur(head.right);
System.out.print(head.value + " ");
}
2、非递归怎么实现
任何递归函数都可以改成非递归函数
准备一个栈,先把头节点放到栈里去
先序遍历:
- 从栈中弹出一个节点cur
- 打印(处理)cur
- 先压右再压左
public static void preOrderUnRecur(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();
}
后序遍历:
准备两个栈,一个收集栈
- 弹出一个节点cur
- cur放入收集栈
- 先左再右压栈
- 收集完了再打印就是后序
public static void posOrderUnRecur1(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();
}
中序遍历(左-右-头)(1:24):
准备一个栈,每棵子树,整棵树左边界进栈,依次弹出的过程中打印,对弹出节点的右树重复。
public static void inOrderUnRecur(Node head) {
System.out.print("in-order: ");
if (head != null) {
Stack<Node> stack = new Stack<Node>();
while (!stack.isEmpty() || head != null) {
if (head != null) {
stack.push(head);
head = head.left;//左边全部压栈
} else {
head = stack.pop();
System.out.print(head.value + " ");//弹出就打印
head = head.right;//换到右边的节点,继续把这个节点的左边界全压栈
}
}
}
System.out.println();
}
二叉树递归和非递归的遍历,必须自己练会。
3、如何直观地打印一个二叉树(就是为了看看图)
具体见文件:
Code02_PrintBinaryTree
4、宽度优先遍历
对于二叉树来说先序遍历就是深度优先遍历,宽度优先遍历就是一层一层打印
准备一个队列,头进尾出也就是先进先出,弹出一个打印一个,先放左再放右,即可实现宽度优先遍历。
用哈希表的方法(1:58)
新手看代码不能硬看,准备纸和笔,人家用什么变量名你就写一模一样的在纸上,一步一步抠。
不用哈希表的方法比用哈希表的方法难得多(2:11)。
二、二叉树的相关概念及其实现判断
- 搜索二叉树指的是根节点比左子节点大,比右子节点小,对于每一个子树都成立。一个简单的办法是中序遍历之后得到的是升序。把中序遍历中打印的环节改成判断的环节即可。
- 完全二叉树指的是每一层全都是满的,即使最后一层不满,也是从左到右依次变满的。按宽度遍历,在依次遍历到每个节点的过程中如果有右子节点没有左子节点,直接返回false。如果没有有右无左的节点,遇到了第一个左右子不全的节点,那么后续全为叶节点才为完全二叉树(0:21)。
- 满二叉树,统计最大深度L,统计节点个数N,N=2^L-1
- 平衡二叉树指的是对于任何一个子树来说,左数和右树的高度差不超过1(0:37)。判断一个节点以下构成的子树为平衡二叉树,首先左子树为平衡二叉树,右子树为平衡二叉树,左子树高度和右子树高度差小于1。
!递归结构可以解决一切面试中的树型DP问题!
三、给定两个二叉树的节点node1和node2,找到他们的最低公共祖先节点
1:19
四、
1:48
五、
2:02