给定一个n结点的二叉树,写出一个O(n)时间的非递归过程,将该树每个结点的关键字输出。要求除该树本身的存储空间外只能使用固定量的额外存储空间,且在过程中不得修改该树,即使是暂时的修改也不允许。
先结合上图说下具体的策略
对二叉树进行遍历(图中红色箭头所指方向),在遍历过程中存储两个点,分别是当前遍历的点记为now,以及上一步遍历的点记为last,将now和last均初始化为T.root,同时初始化root_num = 0,该变量表示遍历结点到达根结点的次数。根据now和last的关系,通过以下几种方式进行遍历:
0、检测now是否是根结点T.root,如果是,更新root_num到root_num + 1,root_num到达2时,遍历结束(该步每次更新后均进行)
1、检测last是否是now的left-child,如果是,说明last及其分支下所有结点完成遍历,进入2;若不是,再检测last是否是now的right-child,如果是,说明now及其分支下所有结点完成遍历,进入3;均不是的话,说明仍处于向下遍历过程,进入4
2、(last == now.left-child)检测now是否存在right-child,如果存在,更新last为now,now为now.right-child,同时打印更新后的now关键字(打印策略是只有last为now的父节点时才打印,最后需补打根结点);如果不存在,更新last为now,now为now.parent
3、(last == now.right-child)更新last为now,now为now.parent
4、(last == now or last == now.parent)检测now是否存在left-child,如果存在,更新last为now,now为now.left-child,同时打印更新后的now关键字;如果不存在,再检测now是否存在right-child,如果存在,更新last为now,now为now.right-child,同时打印更新后的now关键字;now即不存在left-child,也不存在right-child,说明此时now为叶结点,last和now交换位置
PRINT(T)
root_num = 0 # 标志位,表示遍历到达根结点的次数,达到2时遍历结束
last = now = T.root # last、now初始化为根结点,分别表示上次和本次遍历的点
while root_num != 2
if last == now.left-child
if now.right-child != NIL
last = now
now = now.right-child
print now.key
else
last = now
now = now.parent
if now == T.root
root_num += 1
else if last == now.right-child
last = now
now = now.parent
if now == T.root
root_num += 1
else
if now.left-child != NIL
last = now
now = now.left-child
print now.key
else if now.right-child != NIL
last = now
now = now.right-child
print now.key
else
last, now = now, last
if now == T.root
root_num += 1