二叉树后序遍历的迭代实现

#include <stdio.h>
#include <stdlib.h>
struct BinTreeNode{
    int Element;
    int visited;//用于标记当前节点有没有被访问过
    struct BinTreeNode* Left;
    struct BinTreeNode* Right;
};
//以下代码用于建树,便于测试中序遍历程序是否正确
struct BinTreeNode* CreateNode(int data){//创造新节点
    struct BinTreeNode* temp;
    temp=(struct BinTreeNode*)malloc(sizeof(struct BinTreeNode));
    if(temp!=NULL){
        temp->Element=data;
        temp->visited=0;
        temp->Left=NULL;
        temp->Right=NULL;
    }
    return temp;
}
struct BinTreeNode* FindNode(struct BinTreeNode* BinTree,int data)//查找
{
    if(BinTree==NULL)
        return NULL;
    if(BinTree->Element==data)
        return BinTree;
    struct BinTreeNode* temp=NULL;
    if(BinTree->Left!=NULL)
        temp=FindNode(BinTree->Left,data);
    if(temp==NULL&&BinTree->Right!=NULL)
        temp=FindNode(BinTree->Right,data);
    return temp;

}
//假设每个节点值不同
#define LEFT 1
#define RIGHT 0
struct BinTreeNode* InsertNode(struct BinTreeNode* BinTree,int loc,int dir,int data)//插入节点,loc代表插入的数的父节点的值,dir表示方向
{
    struct BinTreeNode* parent=FindNode(BinTree,loc);
    if(parent!=NULL){
        struct BinTreeNode* temp=CreateNode(data);
        if(dir==LEFT)
            parent->Left=temp;
        else
            parent->Right=temp;
    }
    return BinTree;
}
//二叉树前序遍历的迭代实现,用到栈
/*
思路:
后序不同于前序和中序,后序要访问完左子树和右子树才能访问节点;
因此遍历到一个节点,访不访问他取决于它的左右子树是不是均被访问过了;
需要在结构体中加入一个用来判断的变量visited,如果其左右子树均被访问过,就赋值为1
过程:
当前节点,沿它的左路径,开始遍历,直到路径末尾,开始回溯
回溯过程中的节点的左儿子一定被访问过了或者不存在,如果其右儿子不存在或者右儿子已经被访问过,访问当前节点
如果其右儿子存在,此时以其右儿子为基础,再去遍历其左路径
*/
void PostOrderTrversal(struct BinTreeNode* BinTree)
{
    //建栈
    struct BinTreeNode* stack[100];
    int top=-1;
    int flag;//判断要不要去遍历一个新的 (子)树左路径
    struct BinTreeNode* Temp=BinTree;
    while(Temp!=NULL||top>=0){
        flag=1;
        while(Temp!=NULL){//遍历 (子)树左路径
            Temp->visited=1;
            top++;
            stack[top]=Temp;
            Temp=Temp->Left;
        }
        while(flag&&top>=0){
           if(stack[top]->Right==NULL||stack[top]->Right->visited==1){//右儿子不存在或者右儿子已经被访问过
              printf("%d ",stack[top]->Element);
              top--;
           }
           else{
              Temp=stack[top]->Right;
              flag=0;//flag为0,遍历一个新的 (子)树左路径
           }
        }
    }
    return;
}
int main()
{
    struct BinTreeNode* BinTree;
    //先手工创建一个树  //不提倡此类建树方法,只是暂时用于测试程序
    BinTree=CreateNode(10);
    BinTree=InsertNode(BinTree,10,1,20);
    BinTree=InsertNode(BinTree,10,0,30);
    BinTree=InsertNode(BinTree,30,1,40);
    BinTree=InsertNode(BinTree,40,0,50);
    //遍历
    PostOrderTrversal(BinTree);
    return 0;
}
//不用flag也可以
#include <stdio.h>
#include <stdlib.h>
struct BinTreeNode{
    int Element;
    int visited;//用于标记当前节点有没有被访问过
    struct BinTreeNode* Left;
    struct BinTreeNode* Right;
};
//以下代码用于建树,便于测试中序遍历程序是否正确
struct BinTreeNode* CreateNode(int data){//创造新节点
    struct BinTreeNode* temp;
    temp=(struct BinTreeNode*)malloc(sizeof(struct BinTreeNode));
    if(temp!=NULL){
        temp->Element=data;
        temp->visited=0;
        temp->Left=NULL;
        temp->Right=NULL;
    }
    return temp;
}
struct BinTreeNode* FindNode(struct BinTreeNode* BinTree,int data)//查找
{
    if(BinTree==NULL)
        return NULL;
    if(BinTree->Element==data)
        return BinTree;
    struct BinTreeNode* temp=NULL;
    if(BinTree->Left!=NULL)
        temp=FindNode(BinTree->Left,data);
    if(temp==NULL&&BinTree->Right!=NULL)
        temp=FindNode(BinTree->Right,data);
    return temp;

}
//假设每个节点值不同
#define LEFT 1
#define RIGHT 0
struct BinTreeNode* InsertNode(struct BinTreeNode* BinTree,int loc,int dir,int data)//插入节点,loc代表插入的数的父节点的值,dir表示方向
{
    struct BinTreeNode* parent=FindNode(BinTree,loc);
    if(parent!=NULL){
        struct BinTreeNode* temp=CreateNode(data);
        if(dir==LEFT)
            parent->Left=temp;
        else
            parent->Right=temp;
    }
    return BinTree;
}
//二叉树前序遍历的迭代实现,用到栈
/*
思路:
后序不同于前序和中序,后序要访问完左子树和右子树才能访问节点;
因此遍历到一个节点,访不访问他取决于它的左右子树是不是均被访问过了;
需要在结构体中加入一个用来判断的变量visited,如果其左右子树均被访问过,就赋值为1
过程:
当前节点,沿它的左路径,开始遍历,直到路径末尾,开始回溯
回溯过程中的节点的左儿子一定被访问过了或者不存在,如果其右儿子不存在或者右儿子已经被访问过,访问当前节点
如果其右儿子存在,此时以其右儿子为基础,再去遍历其左路径
*/
void PostOrderTrversal(struct BinTreeNode* BinTree)
{
    //建栈
    struct BinTreeNode* stack[100];
    int top=-1;
    struct BinTreeNode* Temp=BinTree;
    while(Temp!=NULL||top>=0){
        while(Temp!=NULL){//遍历 (子)树左路径
            Temp->visited=1;
            top++;
            stack[top]=Temp;
            Temp=Temp->Left;
        }
        if(top>=0){
           if(stack[top]->Right==NULL||stack[top]->Right->visited==1){//右儿子不存在或者右儿子已经被访问过
              printf("%d ",stack[top]->Element);
              top--;
           }
           else
              Temp=stack[top]->Right;
        }
    }
    return;
}
int main()
{
    struct BinTreeNode* BinTree;
    //先手工创建一个树  //不提倡此类建树方法,只是暂时用于测试程序
    BinTree=CreateNode(10);
    BinTree=InsertNode(BinTree,10,1,20);
    BinTree=InsertNode(BinTree,10,0,30);
    BinTree=InsertNode(BinTree,30,1,40);
    BinTree=InsertNode(BinTree,40,0,50);
    //遍历
    PostOrderTrversal(BinTree);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值