今天把二叉树的非递归遍历算法复习了下,在这总结下。
三个算法都使用了栈,中序和前序遍历算法大致相同,而后序遍历稍微复杂一点。
先写中序遍历。
//S是 栈,存储结点,t是树的根结点
Inorder(t)
//创建栈,将跟结点赋给临时结点p
Create(S),p = t;
//如果根为空,返回
IF t = null THEN RETURN
WHILE p!= null AND S!= null
//当存在左子树的时候,往栈中压栈
WHILE p!= null THEN
S.push(p);
p = left(p);
//如果栈大小为空,则返回
IF S = null THEN RETURN
//否则,弹栈,并打印p节点,将p的左子树压栈
p = S.pop();
PRINT data(p);
p = left(p);
这样一个过程就是中序遍历的过程。
再写前序,类似于中序,只需将打印的位置改一下即可
//S是 栈,存储结点,t是树的根结点
Inorder(t)
//创建栈,将跟结点赋给临时结点p
Create(S),p = t;
//如果根为空,返回
IF t = null THEN RETURN
WHILE p!= null AND S!= null
//当存在左子树的时候,往栈中压栈,打印p
WHILE p!= null THEN
S.push(p);
PRINT data(p);
p = left(p);
//如果栈大小为空,则返回
IF S = null THEN RETURN
//否则,弹栈,并打印p节点,将p的左子树压栈
p = S.pop();
后序遍历,稍微复杂点,需要添加一个标记,树中任意结点都需要进栈三次出栈三次,第一次出栈是为了遍历树的左结点
第二次是为了遍历树的右结点,第三次是为了访问该节点。
//如果根结点为空,返回
IF t = null; THEN RETURN
//创建栈
CREATE(S), S.push(t,0);
//当栈非空时
WHILE S != null
//弹栈
(p,i) = S.pop();
//如果i为0那么表明没遍历过该结点,将左子树压栈
IF i = 0 THEN (S.push(p,1). IF left(p) != null THEN S.push(left(p),0));
//如果i为1那么表明左子树遍历完成,将右子树压栈
IF i = 1 THEN (S.push(p,2). IF righr(p) != null THEN S.push(right(p),0));
//如果i为3,表明左右遍历完毕,打印
IF i = 2 THEN PRINT(data(p));