二叉树:
前序/中序/后序遍历
前序:根 + 左子树的前序(递归)+ 右子树的前序(递归)
中序: 左子树的中序(递归) + 根 + 右子树的中序(递归)
后序: 左子树的后序(递归)+右子树的后序(递归)+ 根
//迭代的方法前序遍历
public static List<Character> preOrder(Node root){
if (root == null){
return new ArrayList<>();
}
List<Character> list = new ArrayList<>();
List<Character> leftPreOrder = preOrder(root.left);
List<Character> rightPreOrder = preOrder(root.right);
list.add(root.value);
list.addAll(leftPreOrder);
list.addAll(rightPreOrder);
return list;
}
//递归:前序遍历
public static void preOrderTraversal(Node root){
if (root == null){
return;
}
//根 + 左子树 + 右子树
System.out.println(root.value);
preOrderTraversal(root.left);
preOrderTraversal(root.right);
}
//递归:中序遍历
public static void inOrderTraversal(Node root){
if (root == null){
return;
}
//左子树 + 根 + 右子树
inOrderTraversal(root.left);
System.out.println(root.value);
inOrderTraversal(root.right);
}
//递归:后序遍历
public static void postOrderTraversal(Node root){
if (root == null){
return;
}
//左子树 + 右子树 + 根
postOrderTraversal(root.left);
postOrderTraversal(root.right);
System.out.println(root.value);
}
递归方法的一些诀窍:
1、不要写方法的就做递归展开,站在自己的角度思考,先不用管其他结点
2、找终止条件,在变化的因素中确定,也就是形参
3、找向下的递推公式
4、理解递归方法的调用过程中,会被调用很多次
5、理解调用过程中,局部变量会有多份,只是名字一样
非递归求二叉树前序/中序/后序 遍历
代码:
public static void preorderNoR(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (!stack.empty() || cur != null) {
while (cur != null) {
System.out.println(cur.val);
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.pop();
cur = top.right;
}
}
public static void inorderNoR(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (!stack.empty() || cur != null) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.pop();
System.out.println(top.val);
cur = top.right;
}
}
public static void postorderNoR(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode last = null; // 上一个被三次完整经过的结点
while (!stack.empty() || cur != null) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.peek();
if (top.right == null || top.right == last) {
stack.pop();
System.out.println(top.val);
last = top;
} else {
cur = top.right;
}
}
}
非递归 vs 递归:栈空间更容易控制。
各自的优势:
a、递归使用的栈是系统调用栈,往往空间比较小,而且一般比较固定大小的
b、自己用非递归,手头实现栈,栈的空间在堆上,一般比较大
c、递归写法更简单
以上是我总结出的一些小的技巧,欢迎大家补充。