- 后序遍历:首先遍历左子树,然后遍历右子树,最后访问根节点(左->右->根)
后序遍历的递归算法
思路:
- 遍历左子树
- 遍历右子树
- 访问根节点
代码如下:
//二叉树的后序遍历(递归)
void BinaryTreePostOrder(BTNode* root){
if (root){
BinaryTreePostOrder(root->lChild);
BinaryTreePostOrder(root->rChild);
putchar(root->data);
}
}
后序遍历的非递归算法
思路:
借助栈来实现
- 传入二叉树根节点
- 从当前节点开始遍历左子树,将所有的节点入栈,且清空LT标记,直至左子树为空
- 访问栈顶,将其LT置位为1,访问他的右子树(如果右子树存在,返回至步骤2,如果右子树不存在,则继续执行)
- 取出栈顶并打印(出栈),通过检测他的父节点的LT是否也被置位为1(如果是,则一直打印并出栈,直到找到一个LT标记为清空状态的节点位置,返回至步骤2)
图解后续遍历的非递归算法
代码如下:
//二叉树的后序遍历(非递归)
void BinaryTreePostOrderNonR(BTNode* root)
{
char tag[64];
BTNode * cur = root;
Stack st;
StackInit(&st, 100);
do{
for (; cur; cur = cur->lChild) //类似中序,将当前节点及其左孩子们入栈
{
StackPush(&st, cur);
tag[st.size - 1] = 0; //重置左子树访问标记(LT)
}
while (!StackIsEmpty(&st) && tag[st.size - 1])
//前面的条件只在最后一次循环跳出的时候生效
//后面的条件分两个情况:
//1、当cur为空时,上面的for不进,此条件成立
//2、当cur不为空,上面的for进,则此条件不成立
//如果检测到当前的LT被置位(也就是情况1),那么在打印完当前节点后,再去直接检查上一个节点(父节点)是不是也要被打印了(LT置位,证明这是它的右子树,它也要被打印了),所以要用while循环打印
{
cur = StackTop(&st);
putchar(cur->data);
StackPop(&st);
}
if (!StackIsEmpty(&st)) //此条件只在最后一次循环跳出时生效
{
cur = StackTop(&st);
//1、如果上面的while进了,那么证明左子树访问完毕了,给LT置位
//2、如果上面的while没进,那么证明左子树不存在,给LT置位
tag[st.size - 1] = 1;
cur = cur->rChild;
//左子树访问完毕后,访问右子树
}
} while (!StackIsEmpty(&st));
//由于后序遍历中根节点是最后出栈的,所以在根节点出栈前,栈不可能为空
//所以以栈是否为空来判定是否要跳出
StackDestory(&st);
}
栈函数实现如下:
typedef char BTDataType;
// 二叉链的结构体
typedef struct BinaryTreeNode {
BTDataType data; // 当前节点值域
struct BinTreeNode* lChild; // 指向当前节点左孩子
struct BinTreeNode* rChild;// 指向当前节点右孩子
}BTNode;
typedef BTNode* StDataType;
// 栈的结构体
typedef struct Stack {
StDataType* array; // 指向动态开辟的数组
size_t size; // 有效数据个数
size_t capicity; // 容量空间的大小
}Stack;
void StackInit(Stack* psl, size_t capicity)
{
assert(psl);
psl->capicity = capicity;
psl->array = (StDataType *)malloc(capicity * sizeof(StDataType));
assert(psl->array);
psl->size = 0;
}
void StackDestory(Stack* psl)
{
assert(psl);
if (psl->array)
{
free(psl->array);
psl->array = NULL;
psl->size = 0;
psl->capicity = 0;
}
}
void CheckCapacity(Stack* psl)
{
assert(psl);
if (psl->size == psl->capicity)
{
psl->capicity *= 2;
psl->array = (StDataType *)realloc(psl->array, psl->capicity * sizeof(StDataType));
}
}
void StackPush(Stack* psl, StDataType x)
{
assert(psl);
CheckCapacity(psl);
psl->array[psl->size] = x;
psl->size++;
}
void StackPop(Stack* psl)
{
assert(psl || psl->size);
psl->size--;
}
StDataType StackTop(Stack* psl)
{
if (StackIsEmpty(psl))
{
return (StDataType)0;
}
return psl->array[psl->size - 1];
}
int StackIsEmpty(Stack* psl)
{
return psl->size == 0;
}