二叉树遍历非递归算法——后序遍历
在前面先后介绍了二叉树先序遍历的非递归算法和中序遍历的非递归算法,这里则来介绍二叉树后序遍历非递归算法,二叉树后序非递归遍历真的非常之
重要,因为它具有独特的特性(文章结尾会阐述),所以,在很多与二叉树相关的复杂算法中,经常要用到二叉树后序遍历的非递归算法。并且在互联网面试笔
试也经常考察该算法,所以,我们应该对二叉树后序遍历非递归算法乱熟于心。
和二叉树先序遍历、中序遍历非递归算法一样,后序遍历非递归算法同样是使用栈来实现:从根结点开始,将所有最左结点全部压栈,每当一个结点出栈时,
都先扫描该结点的右子树,只有当一个结点的左孩子和右孩子结点均被访问过了,才能访问结点自身。
二叉树后序遍历非递归算法实现如下:
#include <stdlib.h> #include <stdio.h> #define MAXSIZE 100 // 定义结点类型 typedef struct node { int data; struct node* lchild; struct node* rchild; } BTnode; void Postorder(BTnode* t) { BTnode* Seqstack[MAXSIZE]; int top = -1; int falg = 1; BTnode* p; if(t != NULL) { do { while(t != NULL) // 循环,将所有最左结点压栈 { top ++; Seqstack[top] = t; t = t->lchild; } flag = 1; // 辅助变量flag为1表示当前结点的左孩子为空或者已被访问 p = NULL; // 指针变量p指向当前结点的前驱结点 while(top > -1&& falg == 1) { t = Seqstack[top]; // 注意:这里只是获取栈顶元素,而并没有出栈 if(t->rchild == p) // 如果当前结点右孩子为空,或者已经被访问过,则访问当前结点 { top --; // 当前结点出栈 printf("%d ", p->data); p = t; // 指针变量指向当前结点 } else // 如果当前结点右孩子不为空,则先去处理右孩子 { t = t->rchild; // 处理右孩子 flag = 0; // *t的左孩子未被访问,flag置为0 } } }while(top > -1) } }
上面代码实现了二叉树后序遍历非递归算法(重点看懂注释),接下来就说一说前面提到的该算法的一个特性了:就是当访问某个结点时,栈中所保存的元素
正好是这个结点的所有祖先。那么知道了这个特性,我们就很容易解决下面如下问题:
(1).当给定一个叶子结点,要求输出该叶子结点的所有祖先
(2).输出根结点到所有叶子结点的路径
(3).如果二叉树结点的值是数值,那么求每条路径上值之和,也可以利用二叉树后序遍历的非递归算法这个特性