1. 前序遍历
前序遍历根在最前面。实现起来比较简单,使用一个栈就OK了。
对于每一个节点,我们直接访问它,并把它的右儿子压入栈中,之后我们移动指针来访问左儿子。
到头了之后就把右儿子从站里pop出来。
ClearStack(S); p = bt; while (1){ if (p == NULL){ if (EmptyStack(S)) break; p = Pop(S); } visit(p); if (p->Rchild != NULL) Push(S, p->Rchild); p = p->Lchild; }
2.中序遍历
中序遍历的难度和前序类似。首先我们从根节点出发,一路向左走到最左边。期间遇到的节点都压栈。
之后,我们从最左侧开始访问栈中节点,并访问其右子树。
ClearStack(S); p = bt; while (1){ while (p){ Push(S, p); p = p->Lchild; } if (EmptyStack(S)) break; //此时应访问刚进栈的 p = Pop(S); visit(p); p = p->Rchild; //访问右子树 }
3.后序遍历
后序遍历相比起来复杂一些,但基本思路和中序类似。
后序遍历的顺序是 左-右-根,同样需要先向左走到头,但是回头的时候不能立刻访问根节点,而是用结构体标记一下,继续入栈,之后继续访问右节点并遍历。如果出栈的根节点是标记过的,那才说明它下面的节点都被访问过了,可以放心pop出去。
//定义栈元素类型: typedef struct { BTptr q; //节点地址 int tag; //标志 } STYPE; STYPE sdata; ClearStack(S); p = bt; while (1) { while (p) { sdata.q = p; sdata.tag = 0; Push(S, sdata); p = p->Lchild; } if (EmptyStack(S)) break; sdata = Pop(S); p = sdata.q; tag = sdata.tag; if (tag == 0) //应先遍历右子树 { sdata.tag = 1; Push(S, sdata); p = p->Rchild; // 访问右子树 } else { visit(p); p = NULL; } }