1.为什么后序遍历不能像前中序遍历的非递归写法一样简洁?
前中后序的差异在于节点访问的时序。
前序遍历的根节点访问在遍历左子树的同时就可以完成,实际上前序遍历并不仅仅是访问根节点。同时,它还访问了结点的左孩子结点,也就是孩子结点是相对于双亲结点来说的,访问了该节点也就是访问了其双亲结点的左孩子结点,剩下的工作就是完成右孩子结点的访问。这时候也是将左节点和根节点以及一个未知的右子树结点构成的一个根左右的前序遍历。没有一个二叉树会没有叶子结点,这个时候叶子结点已经被当做根节点处理,结束整个循环。
而中序遍历无法在遍历左子树时完成根节点访问,因为在遍历左子树时完成的根节点访问一定是先根后左,而不是先左后根。所以要先遍历完左子树到叶子结点,然后将每一个栈顶元素作为根节点被访问(触发问题2),此时的根节点也是左孩子,同一个访问被赋予了两重含义,顺序是先作为根节点访问再在向上时作为左孩子访问。
而后序遍历是在访问过左右孩子之后再访问根节点,所以同样是先一左到底,进行了右子树遍历的结点可以出栈并访问。
2.为什么中序遍历时将每一个栈顶元素看做根节点&左孩子?
【教材原文:在遍历过程中遇到某结点时并不能立即访问它,而是将它压栈,等到其左子树遍历完,弹栈访问之。】
也就是说,当某一结点的左子树遍历完,自然是以先左的顺序访问,而此时位于叶子结点,无左右孩子,从而向上访问其双亲结点。访问完双亲结点后,遍历其右子树(触发问题3),再次遍历左子树,向上访问双亲,并遍历右子树。这个循环的过程可以看做左节点和根节点以及一个未知的右子树结点构成的一个左根右的中序遍历。
3.为什么右子树的遍历不像左子树一样遍历到底?
左右子树的访问始终是先左后右,所以每次右子树的遍历都以已经进行过左子树遍历的结点为起点,但这个遍历并不是一遍到底,其中每一个结点都要进行左子树遍历【再次进入一开始的步骤】,直至叶子结点出现,无左右孩子,从而向上访问其双亲结点。访问完双亲结点后,遍历其右子树。【出现了和上文一样的步骤】。最关键的地方在于,右子树的遍历以没有左子树的节点的出现为结束条件。也就是说,没有一个二叉树会一直出现有左子树的结点,最后总会出现一个叶子结点,没有左孩子也没有右孩子,以此终结右子树的遍历。