树_遍历二叉树

本文详细介绍了二叉树的四种遍历方法:先序、中序、后序和层序遍历。对于每种遍历,都提供了递归和非递归(栈实现)的算法,并展示了如何通过栈来辅助非递归遍历。此外,还提到了以线索链表为存储结构的中序遍历,以及中序线索化的实现方法。
摘要由CSDN通过智能技术生成

遍历二叉树

首先判断是否为空树

一、以二叉链表为存储结构

/*-----二叉树的二叉链表的存储结构-----*/
typedef int Telemtype;
typedef struct BiTNode 
{
    Telemtype data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
  • 递归算法注意设置递归出口。
  • 非递归算法用栈实现,栈用来保存走过的路径。

非递归算法中,后序遍历要判断,在返回根结点时,是从左子树返回还是右子树返回。设置一个标志量,加入二叉链表结点中。

1.先序遍历二叉链表
递归算法
/*-----先序遍历二叉树的二叉链表,递归算法-----*/
void preorder_traverse(BiTree T)
{
    if(T==NULL) return;//递归出口,空树
    printf("%d",T->data);
    preorder_traverse(T->lchild);
    preorder_traverse(T->rchild);
}
非递归算法
/*先序遍历二叉树的二叉链表,非递归算法,用栈实现*/
void inorder_traverse(BiTree T)
{
    BiTree p=T;
    InitStack(S);//初始化栈
    while(p||!StackEmpty(S))
    {
        if(p!=NULL)//根指针进栈,访问根结点,遍历左子树
        {
            Push(S,p);
            printf("%d",p->data);//访问根结点
            p=p->lchild;//遍历左子树
        }
       else//根结点退栈,遍历右子树
        {
            Pop(S,p);
            p=p->rchild;//遍历右子树
        }
    }
}
/*先序遍历二叉树的二叉链表,非递归算法,用栈实现,与上一个比较*/
void inorder_traverse(BiTree T)
{
    BiTree p=T;
    InitStack(S);//初始化栈
    while(p||!StackEmpty(S))
    {
        while(p!=NULL)//一直遍历到左子树最下边,边遍历边访问并保存根节点到栈中(路径)
        {
            Push(S,p);
            printf("%d",p->data);//访问根结点,入栈
            p=p->lchild;//遍历左子树
        }
        if(!StackEmpty(S))//根结点出栈,遍历右子树
        {
            Pop(S,p);
            p=p->rchild;//遍历右子树
        }
    }
}
2.中序遍历二叉树
递归算法
/*中序遍历二叉树的二叉链表,递归算法*/
void preorder_traverse(BiTree T)
{
    if(T==NULL) return;//递归出口,空树
    preorder_traverse(T->lchild);
    printf("%d",T->data);
    preorder_traverse(T->rchild);
}
非递归算法
/*中序遍历二叉树的二叉链表,非递归算法,用栈实现*/
void inorder_traverse(BiTree T)
{
    BiTree p=T;
    InitStack(S);//初始化栈
    while(p||!StackEmpty(S))
    {
        if(p!=NULL)//根指针进栈,遍历左子树
        {
            Push(S,p);
            p=p->lchild;//遍历左子树
        }
       else//根指针退栈,访问根结点,遍历右子树
        {
            Pop(S,p);
            printf("%d",p->data);//访问根结点
            p=p->rchild;//遍历右子树
        }
    }
}
/*中序遍历二叉树的二叉链表,非递归算法,用栈实现,与上一个比较*/
void inorder_traverse(BiTree T)
{
    BiTree p=T;
    InitStack(S);//初始化栈
    while(p||!StackEmpty(S))
    {
        while(p!=NULL)//一直遍历到左子树最下边,边遍历边保存根节点到栈中(路径)
        {
            Push(S,p);
            p=p->lchild;//保存路径
        }
        if(!StackEmpty(S))
        {
            Pop(S,p);
            printf("%d",p->data);//出栈,访问根结点
            p=p->rchild;//遍历右子树
        }
    }
}
3.后序遍历二叉树
递归算法
/*后序遍历二叉树的二叉链表,递归算法*/
void preorder_traverse(BiTree T)
{
    if(T==NULL) return;//递归出口,空树
    preorder_traverse(T->lchild);
    preorder_traverse(T->rchild);
    printf("%d",T->data);
}
/*后序遍历二叉树的二叉链表,非递归算法,用栈实现*/
/*设置一个标志量flag,加入结点中0表示从左子树返回,1表示从右子树返回。只有从右子树返回时,才访问根结点*/
void inorder_traverse(BiTree T)
{
    BiTree p=T;
    InitStack(S);//初始化栈
    while(p||!StackEmpty(S))
    {
        if(p!=NULL)//根指针进栈,遍历左子树
        {
            Push(S,p);
            p->flag=0;//去访问该结点的左子树
            p=p->lchild;//遍历左子树
        }
       else//第一个else
        {
            Pop(S,p);//根结点先出栈,判断是否要访问
            if(p->flag==0)//只访问过左子树,不访问根结点
            {
                Push(S,p);//根结点重新入栈,保存路线
                p->flag=1;//去访问该结点的右子树
                p=p->rchild;//遍历右子树
            }
            else//右子树访问过,访问根结点,根结点已退栈
            {
                printf("%d",p->data);//访问根结点
                p=NULL;//注意置空指针!
                /*NULL使之进入第一个else,根结点再次退栈,判断从左子树还是右子树退栈*/
            }
           
        }
    }
}
4.层序遍历二叉树

使用队列实现

/*层序遍历二叉树的二叉链表,用队列实现*/
void levelorder_traverse(BiTree T)
{
    //判断是否为空树
    if(T==NULL) return;
    InitQueue(Q);//初始化队列
    Push(Q,T);//根结点入队
    while(!QueueEmpty(Q))
    {
        BiTree p=front(Q);//取队头元素,访问
        printf("%d",p->data);
        if(p->lchild!=NULL)//左子树不为空则入队
            Push(Q,T);//根结点入队
        if(p->rchild!=NULL)//右子树不为空则入队
           Push(Q,T);//根结点入队
    }
}

可推广到用队列实现树的层序遍历

二、 以线索链表为存储结构

中序遍历
/*中序遍历二叉树的双向线索链表,非递归算法,不需要用栈*/
void inorder_traverse_Thr(BiThrTree T)//T为头结点
{
    BiThrTree p=T->lchild;//p指向根结点
    while(p!=T)//非空树或遍历未结束
    {
        while(p->LTag==Link)//遍历左子树
            p=p->lchild;
        printf("%d",p->data);//访问根结点
       
        while(p->RTag==Thread&&p->rchild!=T)
        {
            p=p->rchild;//访问后继节点
            printf("%d",p->data);
        }
        p=p->rchild;//遍历右子树
    }
}
中序线索化二叉链表
/*中序线索化二叉树的双向线索链表,Thrt为头结点*/
BiThrTree pre;//全局变量

void inorder_Threading(BiThrTree T,BiThrTree /*&*/ Thrt)
{
    //建头结点,为头结点Thrt分配空间
    if(!(Thrt=(BiThrTree)malloc(sizeof(BiThrNode))))  exit(0);
    Thrt->LTag=Link;Thrt->RTag=Thread;
    Thrt->rchild=Thrt;//右指针回指
    if(T==NULL) Thrt->lchild=Thrt;//若二叉树为空,则左指针回指
    else
    {
        Thrt->lchild=T;//双向
        pre=Thrt;
        InThreading(T);//中序线索化二叉树
        pre->RTag=Thread;pre->rchild=Thrt;//最后一个结点线索化
        Thrt->rchild=pre;//双向
    }
}

/*中序线索化二叉树,递归算法*/
void InThreading(BiThrTree p)
{
    if(p==NULL) return;//递归出口
    //左子树线索化
    InThreading(p->lchild);
    //若遇到左子树为空,即左指针为空指针,前驱线索
    if(p->lchild==NULL)
    {
        p->LTag=Thread;p->lchild=pre;
    }
    //若遇到右子树为空,即右指针为空指针,后继线索
    if(pre->rchild==NULL)
    {
        pre->RTag=Thread;pre->rchild=p;
    }
    //保持pre指向p的前驱
    pre=p;
    //右子树线索化
    InThreading(p->rchild);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值