后序遍历是 左右根 是遍历里面最复杂的
后续遍历 两种方法
1.递归
void print4(struct node*root)
{
if(root!=NULL)
{
print4(root->left); //传 当前节点的左节点 (左)
print4(root->right); //传 当前节点的右节点 (右)
printf("%d\t",root->data);//打印 节点 (根)
}
}
递归
分析:
假设遍历如图的二叉树
在非递归里面 中序和后续有相同的地方 先来分析分析 中序遍历 和后序遍历的结果
中序: 30--40--45--........
后续: 30--45--40--........
如果我们按照 中序遍历的思路来
可以见的 当pnode到45这个节点在出栈就是 a[i](a[0]=50)
为了避免它这次出栈到 50 这个节点 所有我们在中间在 入栈 也就是说 后序遍历入栈多次
那遍历的结果就是:30--40--45--40.....
但是我后序遍历是:30--45--40......
只要我们想办法把这个40给(‘删除’)的话那遍历的结果就对了
我们在回过来仔细想想 后序打印 先是30 和 45 他们有一个共同点 就是没有子节点 而40 是把30 和 45 都打印 了才 打印 只要我们在遍历30 和 45 的时候给他们一个标记 当标记存在的时候就可以打印
没有标记不打印 这样30-- 40 --45--40......前面的40就打印不出来了
代码实现
//后续遍历 非递归
void print5(struct node*root)
{
struct node*a[20]; //结构体数组
struct node*pnode=root;
struct node*x=NULL; //标记
int i=-1;
while(pnode)
{
a[++i]=pnode; //入栈
pnode=pnode->left;
}
while(i!=-1)//无路可走的时候
{
pnode=a[i--]; //出栈
if(pnode->right==NULL || pnode->right==x) //当右边为空 或者 被标记
{
printf("%d\t",pnode->data);
x=pnode; //给节点标记
}
else
{
a[++i]=pnode; //入栈
pnode=pnode->right;
while(pnode)
{
a[++i]=pnode;//入栈
pnode=pnode->left;
}
}
}
}