我们知道递归遍历树的方式:对于树的访问先是从根节点开始进行的,递归左子树和右子树,对于左子树和右子树又可以看成是一棵子树继续递归下去,访问根节点的时候它不是直接处理根节点的而是需要等待它的左子树调用完之后那么才进行处理的,左子树也是一样,当访问到它的左子树的时候也需要等待它的左子树处理完毕才处理自己。
这也就是先访问,后出现的特点,与一种数据结构的特点是类似的,那就是栈,栈也是 "先进后出" 的特点,其实递归来说其实就是一种隐式的栈,所以当我们采用非递归形式的时候我们可以自己声明一个栈,模仿递归求解的过程来进行处理
非递归算法思想:
(1)设置一个栈S存放所经过的根结点(指针)信息;初始化S;
(2)第一次访问到根结点并不访问,而是入栈;
(3)中序遍历它的左子树,左子树遍历结束后,第二次遇到根结点,就将根结点(指针)退栈,并且访问根结点;然后中序遍历它的右子树。
(4) 当需要退栈时,如果栈为空则结束。
图解:
public static void main(String[] args) {
Test t = new Test();
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
Node node6 = new Node(6);
Node node7 = new Node(7);
node4.left = node2;
node4.right = node6;
node2.left = node1;
node2.right = node5;
node6.left = node3;
node6.right = node7;
t.midOrder(node4);
}
/* 10
8 12
5 9 11 15
3
*/
public void midOrder(Node root) {
if (root == null) {
return;
}
Stack<Node> stack = new Stack<>();
Node p = root;
while (p != null || !stack.isEmpty()) {
// p不为空压栈
if (p != null) {//不断将左子树结点都压进去
stack.push(p);
p = p.left;
} else {// p为空stack不为空出栈并访问
Node poll = stack.pop();//从最后的左子树结点开始访问
System.out.println(poll.value);
//一旦poll右结点不为空,继续将其放入栈中,接着找到右结点全部的左子结点,即中序遍历poll的右子树
p = poll.right;
}
}
// while 循环退出时,p为空,stack为空,全部都遍历了一边
}