二叉树基础:
重新学习了一下二叉树,要能记住集中最常见的二叉树:
- 满二叉树(perfect binary tree)
- 完全二叉树(complete binary tree)
- 二叉搜索树(binary search tree)
- 平衡二叉搜索树(balanced binary search tree 或者 AVL tree)
几种常见的遍历方法:
- 深度优先遍历
- 前序遍历(递归法,迭代法)(中左右)
- 中序遍历(递归法,迭代法)(左中右)
- 后序遍历(递归法,迭代法)(左右中)
- 广度优先遍历
- 层次遍历(迭代法)
还要记住如何手搓二叉树:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
递归遍历:
跟着题解的递归思路想一遍就比较清晰了,没什么难度,重点还是把递归搞清楚。
迭代遍历:
中序有一定难度,一个关键是用null结点来表示两种情况:
- 当前节点没有更深的左子节点了,记录当前栈顶的节点值并查找它的右节点
- 刚才的节点没有右子节点,记录当前栈顶的节点值(中点)并继续向右查找。
只要栈不为空或当前节点不是null,就不应该退出while-loop,因为遍历完所有根节点左边的子节点之后栈会弹出并记录根节点,此时栈是空的,但根节点右边的子节点还没开始遍历(如果没有任何右子节点则会满足退出条件)。
前序比较容易理解,在纸上画几个例子跟着过一下就差不多了。
后序的反转虽然很轻松就能实现,但理解起来花了我不少时间,最后在纸上写了一下才算是把思路理清楚:
统一迭代法:
一开始完全看不懂,然后自己在纸上跟着题解画图写步骤一步一步来弄明白了。
这种方法理解之后能通过小修改就达成多种遍历方法,很方便,统一迭代法对于栈的应用与上文的各自迭代法有一些不同,几个重点:
- 各自迭代法有时碰到中节点会直接pop并且记录,但统一迭代法大致都是把所有或者一个完整的子树记录好之后才开始往结果数组里记录
- 因此做统一迭代法的时候把目标结果数组反转过来就可以得到大致的目标栈,然后根据这个目标栈去写代码会容易一点
- 因为统一迭代法只有在碰到null节点才会开始往结果数组里记录数据,所以当前节点、当前节点的子左右节点、和null节点的入栈顺序决定了结果数组的遍历顺序
- 在把一个节点和其子节点入栈的时候一定要注意不要重复把一个节点入栈
- 弄不明白的时候一定要在纸上推演