一、非递归先序遍历
方法:
1、创建一个栈;
2、把根节点入栈;
3、取出栈顶元素,访问这个节点;
4、把当前节点的右子树入栈,左子树入栈(非空);
5、回到3重复执行。
源程序:
public static void preOrderByLoop(TreeNode root) {
if (root == null) {
return;
}
// 创建一个栈
Stack<TreeNode> stack = new Stack<>();
// 把根节点入闸
stack.push(root);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
System.out.print(cur);
if (cur.right != null) {
stack.push(cur.right);
}
if (cur.left != null) {
stack.push(cur.left);
}
}
}
二、非递归中序遍历
方法:
1、创建一个栈;
2、创建一个引用cur,从root 出发,一路向左跑.遇到的非空节点都入栈,当cur遇到null的时候,就循环结束;
3、取出栈顶元素,并访问(中序的特点就是一路往左找,遇到某个节点的左子树为空,才能访问根节点);
4、让 cur指向该节点的右子树,回到2继续执行。
源程序:
public static void inOrderByLoop(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (true) {
// 里层循环负责 cur 往左走并入栈这件事
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
// 当上面循环结束, cur 就已经是 null
// 取出栈顶元素, 并且访问
if (stack.isEmpty()) {
// 遍历完了
break;
}
TreeNode top = stack.pop();
System.out.print(top.val);
// 让 cur 从 top 的右子树出发重复上述过程
cur = top.right;
}
}
三、非递归后序遍历
方法:
1、创建一个栈;
2、搞一个cur引用,从root出发,一路往左走,遇到非空节点就入栈,遇到空就停止;
3、栈顶元素不能立刻访问!!得先判定一下:
a)如果栈顶的右子树为空,那就能访问该元素了,访问同时出栈;
b)如果栈顶元素的右子树前面已经访问过了,也可以访问该元素;
如果当前元素不能被访问,就让cur指向栈顶的右子树,重复执行2。
源程序:
public static void postOrderByLoop(TreeNode root) {
if (root == null) {
return;
}
// 1. 创建一个栈
Stack<TreeNode> stack = new Stack<>();
// 2. 创建一个引用 cur, 从 root 出发
TreeNode cur = root;
// 使用 prev 表示遍历结果的前一个元素
TreeNode prev = null;
while (true) {
// 3. 让 cur 往左走, 遇到非空节点就入栈
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
// 4. 取出栈顶元素判断下能不能访问
if (stack.isEmpty()) {
// 遍历结束了
break;
}
// 此处不能直接 pop, 该节点能不能访问还不知道呢.
// 必须是访问了才能出栈
TreeNode top = stack.peek();
if (top.right == null || top.right == prev) {
// 都能访问该节点
System.out.print(top.val);
stack.pop();
prev = top; // 更新 prev 的指向
} else {
cur = top.right;
}
}
}
三、非递归层序遍历
方法:
1、先把根节点放到队列里;
2、进行出队列操作,并且访问这个节点
3、把当前节点的左子树和右子树再入队列(空树就不管了);
4、回到2继续循环执行。
源程序:
public static void levelOrder(TreeNode root) {
if (root == null) {
return;
}
// 创建一个队列
Queue<TreeNode> queue = new LinkedList<>();
// 把根节点入队列
queue.offer(root);
// 循环取队列中的队首元素
while (true) {
TreeNode cur = queue.poll();
if (cur == null) {
break;
}
// 访问当前节点, 直接打印
System.out.print(cur.val);
// 把左右子树入队列
if (cur.left != null) {
queue.offer(cur.left);
}
if (cur.right != null) {
queue.offer(cur.right);
}
}
}