关于二叉树的3种遍历方式原理,原文博主已经详细介绍了,这里只附上非递归形式的Java代码。
原文地址:http://blog.csdn.net/pi9nc/article/details/13008511/
关于二叉树,请参考另一篇文章:http://blog.csdn.net/ifleetingtime/article/details/78836638
/**
* 非递归,遍历整个树
* 中序遍历
* 顺序: 左子节点 -> 父节点 -> 右子节点
*/
public void in_traverse() {
if (root == null)
return ;
Stack<Node> stack = new Stack<>(); // 暂存节点
Node currentNode = root;
while (true) {
if (currentNode.getLeftNode() != null) {
stack.push(currentNode); // 将当前节点 A 入栈
currentNode = currentNode.getLeftNode(); // 如果当前节点有左子节点,继续执行左子节点
}
else {
System.out.print(currentNode.getData() + " ");
currentNode = currentNode.getRightNode(); // 将此节点A 从栈中拿出来,获取它的右子节点
while (currentNode==null && !stack.isEmpty()) {
currentNode = stack.pop(); // A的右子节点为空,继续出栈,找父节点
System.out.print(currentNode.getData() + " "); // 找到父节点之后,先打印父节点,再去找其右节点
currentNode = currentNode.getRightNode();
}
if (currentNode == null) // 如果栈空了,没有找到右子节点,则循环完成
break;
// else continue // 否则 将右子节点作为当前节点继续遍历
}
}
}
/**
* 非递归,遍历整个树
* 前序遍历
* 顺序: 父节点 -> 左子节点 -> 右子节点
*/
public void pre_traverse() {
if (root == null)
return ;
Stack<Node> stack = new Stack<>(); // 暂存节点
Node currentNode = root;
while (true) {
System.out.print(currentNode.getData() + " ");
stack.push(currentNode); // 将当前节点 A 入栈
if (currentNode.getLeftNode() != null) {
currentNode = currentNode.getLeftNode(); // 如果当前节点有左子节点,继续执行左子节点
}
else {
currentNode = stack.pop().getRightNode(); // 将此节点A 从栈中拿出来,上面刚放进去,获取它的右子节点
while (currentNode==null && !stack.isEmpty()) {
currentNode = stack.pop().getRightNode(); // A的右子节点为空,继续出栈,找父节点的右子节点, 找到第一个存在的右子节点
}
if (currentNode == null) // 如果栈空了,没有找到右子节点,则循环完成
break;
// else continue // 否则 将右子节点作为当前节点继续遍历
}
}
}
/**
* 非递归,遍历整个树
* 后序遍历
* 顺序: 左子节点 -> 右子节点 -> 父节点
*/
public void post_traverse() {
if (root == null)
return ;
Stack<Node> stack = new Stack<>(); // 暂存节点
Node currentNode = root;
Node lastNode = null; // 暂存上一个数据的节点
stack.push(currentNode); // 先将根节点入栈
while (!stack.isEmpty()) {
currentNode = stack.peek(); // 获取栈顶元素,不要移除它,不移除的原因: 子节点可能没遍历到,要把子节点压在这个节点上面,先执行子节点
// 如果此时的元素没有左右节点,或者左右节点已经被遍历过了,因为是自下向上遍历,子节点永远是父节点之前紧挨着遍历到的,所以我们用一个lastNode变量保存上一个遍历到的节点
if ( (currentNode.getLeftNode()==null && currentNode.getRightNode()==null) ||
( lastNode!=null && (currentNode.getLeftNode()==lastNode || currentNode.getRightNode()==lastNode) )
)
{
System.out.print(currentNode.getData() + " ");
lastNode = currentNode;
stack.pop(); // 这个节点自身,和子节点都遍历到了,移除,从父节点开始重新遍历
}
else {
// 先入栈右子节点,再入栈左子节点, 这样从栈中取数据时,先执行左子节点,再执行右子节点
if (currentNode.getRightNode() != null) {
stack.push(currentNode.getRightNode());
}
if (currentNode.getLeftNode() != null) {
stack.push(currentNode.getLeftNode());
}
}
}
}