题目
递归非递归实现二叉树的前序遍历,这里附加:中序遍历,后序遍历。
解法
1. 递归方法:
首先为递归方法,递归方法的思想很简单,就是确定根结点与左右孩子之间的遍历顺序,下面为前序遍历的伪代码;
PREORDER-TREE-WALK(BSTreeNode root):
if root != null:
PRINT root.value;
PREORDER-TREE-WALK(root.left);
PREORDER-TREE-WALK(root.right);
相应的中序遍历和后续遍历,只需要调整访问root.value这个操作在遍历左右孩子之间的顺序即可。
INORDER-TREE-WALK(BSTreeNode root):
if root != null:
INORDER-TREE-WALK(root.left);
PRINT root.value;
INORDER-TREE-WALK(root.right);
POSTORDER-TREE-WALK(BSTreeNode root):
if root != null:
POSTORDER-TREE-WALK(root.left);
POSTORDER-TREE-WALK(root.right);
PRINT root.value;
2. 非递归方法中,三种遍历方式就有区别。
(1) 前序遍历方式:可以使用一个stack模拟递归时的默认栈,在每个栈顶元素出栈时先访问,然后再将它的左右孩子入栈,直至栈为空即可。
PREORDER-TREE-WALK-INTERVAL(BSTreeNode root):
Stack<BSTreeNode> stack;
if root == null;
return null;
stack.push(root);
while !stack.isEmpty():
BSTreeNode node = stack.pop();
PRINT node.value;
if node.left != null:
stack.push(root.left);
if node.right != null:
stack.push(root.right);
(2) 中序遍历:中序遍历的非递归实现方式与前序的不同。但它同样使用一个栈作为辅助空间,首先将从根结点开始的左右左子树中的左孩子加入到栈中,即首先访问最左侧的左孩子,然后访问其根结点,如果根结点有右孩子则继续加入栈中,同样还是先探索右孩子为根结点的左子树中的最左侧孩子。这样就实现了中序遍历的过程。
INORDER-TREE-WALK(BSTreeNode root):
Stack<BSTreeNode> stack;
if root == null:
return null;
BSTreeNode current = root;
while !stack.isEmpty() or current != null:
if current!= null:
stack.push(current);
current = current.left;
else
current = stack.pop();
PRINT current;
current = current.right;
(3) 后序遍历的非递归方式有点复杂,主要思想为,使用两个stack结构:sTraverse和sVisit,每遍历到一个节点则push进sTraverse中,紧接着就将该节点pop出sTraverse并且pop进sVisit中,然后当前节点的左右孩子push入sTraverse,即sTraverse栈中保存的为当前访问节点的左右孩子,sVisit中保存的则是从sTraverse中pop出的每个元素,并且顺序就是先为当前节点,然后为其的左右孩子,又因为stack的特性,当sTraverse为空以后,对sVisit进行依次出栈就得到了正确的后续遍历顺序。
POSTORDER-TREE-WALK-INTERVAL(BSTreeNode root):
Stack<BSTreeNode> sTraverse, sVisit;
if root == null:
return null;
sTraverse.push(root);
while !sTraverse.isEmpty():
BSTreeNode node = sTraverse.pop();
sVisit.push(node);
if node.left != null:
sTraverse.push(node.left);
if node.right != null:
sTraverse.push(node.right);
while !sVisit.isEmpty():
PRINT sVisit.pop();