前言
二叉树的遍历是二叉树的基本操作,是学习二叉树必须要掌握的点,这篇文章来总结下二叉树的非递归遍历的思路及其实现代码
前序遍历
思路
前序遍历的顺序是中左右,我们可以用一个栈来存储其节点。首先将根节点入栈并处理,然后按照先右后左的顺序把子节点压栈。在将节点弹出栈(处理完成)后,继续按照上述逻辑,处理其子节点,直到为栈内没有元素。
实现
public ArrayList<String> preOrderTraversal(TreeNode head){
ArrayList<String> res = new ArrayList<>();
if (head == null) {
return res;
}
Stack<TreeNode> treeNodes = new Stack<>();
treeNodes.push(head);
while (!treeNodes.isEmpty()) {
TreeNode curNode = treeNodes.pop();
// 处理
res.add(curNode.value);
if (curNode.right != null) {
treeNodes.push(curNode.right);
}
if (curNode.left != null) {
treeNodes.push(curNode.left);
}
}
return res;
}
中序遍历
思路
中序遍历跟先序遍历的区别在于,先入栈的节点(中间节点)不是首先被处理的节点,因此不好复用先序遍历的代码。
可以考虑 一直往左找,直到为null,开始处理(pop)stack里的元素并及其右节点。
代码
/**
* 中序遍历:左中右
* 一直往左找,直到为null,开始处理stack里的元素并及其右节点
*/
public List<String> inorderTraversal(TreeNode root) {
ArrayList<String> res = new ArrayList<>();
if (root == null) {
return res;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
if (cur != null) {
stack.add(cur);
cur = cur.left;
}else {
cur = stack.pop();
res.add(cur.value);
cur = cur.right;
}
}
return res;
}
后序遍历
思路
先序遍历的顺序是 中左右 ,后序是 左右中,那么我们可以通过先将先序遍历的左右节点处理顺序调换,然后反正整个结果数组即可
代码
/**
* 后序遍历:左右中
* 调整先序遍历的左右节点的顺序,然后翻转
*/
public ArrayList<String> postorderTraversal(TreeNode head){
ArrayList<String> res = new ArrayList<>();
if (head == null) {
return res;
}
Stack<TreeNode> treeNodes = new Stack<>();
treeNodes.push(head);
while (!treeNodes.isEmpty()) {
TreeNode curNode = treeNodes.pop();
// 处理
res.add(curNode.value);
if (curNode.left != null) {
treeNodes.push(curNode.left);
}
if (curNode.right != null) {
treeNodes.push(curNode.right);
}
}
Collections.reverse(res);
return res;
}
结语
OK,这篇文章到这里就结束了,后面更新二叉树相关的算法题。