二叉树的遍历

简单遍历

  • 先序遍历(DLR)
    若二叉树不空,则:
    (1)访问根结点;
    (2)先序遍历左子树;
    (3)先序遍历右子树。
  • 中序遍历(LDR)
    若二叉树不空,则:
    (1)中序遍历左子树;
    (2)访问根结点;
    (3)中序遍历右子树。
  • 后序遍历(LRD)
    若二叉树不空,则:
    (1)后序遍历左子树;
    (2)后序遍历右子树;
    (3)访问根结点。
    这里写图片描述
  • 二叉树递归遍历程序
#include <stdio.h>
#include <malloc.h>

using namespace std;

typedef struct Node
{
    char data;
    struct Node *Lchild;
    struct Node *Rchild;
}BiTNode, *BiTree;

//前序遍历(根左右)
void PrePrint(BiTree T)
{
    if (T != NULL)
    {
        printf("%c  ", T->data);
        PrePrint(T->Lchild);
        PrePrint(T->Rchild);
    }
}

//中序遍历(左根右)
void MidPrint(BiTree T)
{
    if (T != NULL)
    {
        MidPrint(T->Lchild);
        printf("%c  ", T->data);
        MidPrint(T->Rchild);
    }
}

//后序遍历(左右根)
void LatePrint(BiTree T)
{
    if (T != NULL)
    {
        LatePrint(T->Lchild);
        LatePrint(T->Rchild);
        printf("%c  ", T->data);
    }
}

//按照先序遍历创建二叉树
void PreCreateBiTree(BiTree *Troot)
{
    char input;
    scanf_s("%c", &input);
    //孩子结点为空的部分用.代替
    if (input == '.')
    {
        *Troot = NULL;
    }
    else
    {
        (*Troot) = (BiTree)malloc(sizeof(BiTNode));
        (*Troot)->data = input;
        PreCreateBiTree(&((*Troot)->Lchild));
        PreCreateBiTree(&((*Troot)->Rchild));
    }
}

int main(void)
{
    BiTree T;
    printf("请输入数据建立二叉树(孩子结点为空的部分用‘.’代替): \n");
    PreCreateBiTree(&T);
    printf("\n递归算法前序遍历的结果:");
    PrePrint(T);
    printf("\n递归算法中序遍历的结果:");
    MidPrint(T);
    printf("\n递归算法后序遍历的结果:");
    LatePrint(T);
    printf("\n\n");

    return 0;
}

二叉树非递归遍历

  • 在二叉树的非递归遍历中,需要借助栈来存储结点,先序和中序遍历与简单遍历理解相同,但在循环条件中也要注意判定栈是否为空才能进行栈的出入操作。

  • 需要注意的是,在后序遍历中,根结点是最后被访问的。因此,在遍历过程中,当搜索指针指向某一根结点时,不能立即访问,而要先遍历其左子树,此时根结点进栈。当其左子树遍历完后再搜索到该根结点时,还是不能访问,还需遍历其右子树。所以,此根结点还需再次进栈,当其右子树遍历完后再退栈到到该根结点时,才能被访问。

  • 二叉树递归遍历程序

#include <stdio.h>
#include <malloc.h>
#include <stack>

using namespace std;

typedef struct Node
{
    char data;
    struct Node *Lchild;
    struct Node *Rchild;
}BiTNode, *BiTree;

//按照先序遍历创建二叉树
void PreCreateBiTree(BiTree *Troot)
{
    char input;
    scanf_s("%c", &input);
    //孩子结点为空的部分用.代替
    if (input == '.')
    {
        *Troot = NULL;
    }
    else
    {
        (*Troot) = (BiTree)malloc(sizeof(BiTNode));
        (*Troot)->data = input;
        PreCreateBiTree(&((*Troot)->Lchild));
        PreCreateBiTree(&((*Troot)->Rchild));
    }
}

//非递归先序遍历二叉树(根左右)
void New_PrePrint(BiTree Troot)
{
    stack<BiTree> s;
    BiTree root;
    root = Troot;

    while (root != NULL||!s.empty())    //当根结点不为空或者栈中有元素时不断遍历
    {
        if (root != NULL)
        {
            printf("%c  ", root->data);  //打印访问到的结点
            s.push(root);                
            root = root->Lchild;         //开始访问左孩子
        }
        else
        {
            root = s.top();        //当访问到的左结点为空时,使其返回到其父结点的位置
            s.pop();               //该位置的值无用,从栈中弹出
            root = root->Rchild;   //开始访问右孩子
        }
    }
}

//非递归中序遍历二叉树(左根右)
void New_MidPrint(BiTree Troot)
{
    stack<BiTree> s;
    BiTree root;
    root = Troot;
    while (root != NULL||!s.empty())
    {
        if (root != NULL)
        {
            s.push(root);         //先将访问到的元素存入栈中
            root = root->Lchild;  //不断访问左孩子
        }
        else
        {
            root = s.top();              //当访问到的左结点为空时,使其返回到其父结点的位置
            s.pop();
            printf("%c  ", root->data);  //打印这个没有左孩子的点。然后开始访问它的右孩子
            root = root->Rchild;
        }
    }
}

//非递归后序遍历二叉树(左右根)
void New_LatePrint(BiTree Troot)
{
    stack<BiTree> s;
    BiTree root, old;
    root = Troot;
    old = NULL;       //记录已被访问过的结点
    while (root != NULL||!s.empty())
    {
        while (root != NULL)
        {
            //将访问到的左孩子不断压入栈中
            s.push(root);
            root = root->Lchild;
        }
        if (!s.empty())
        {
            root = s.top();            //使top指向刚才所访问结点的父结点
            //先判断当前结点是否可以输出,再访问其右孩子
            //如果该结点没有右孩子,或者其右孩子已被访问过,则可以输出
            if (root->Rchild == NULL || root->Rchild == old)
            {
                printf("%c  ", root->data);
                old = root;            //将当前结点设置为已访问过
                s.pop();
                root = NULL;
            }
            //当前结点不能输出,则继续访问其右孩子
            else
            {
                root = root->Rchild;
            }
        }
    }

}

int main(void)
{
    BiTree T;

    printf("请输入数据建立二叉树(孩子结点为空的部分用‘.’代替): \n");
    PreCreateBiTree(&T);
    printf("\n非递归算法前序遍历的结果:");
    New_PrePrint(T);
    printf("\n非递归算法中序遍历的结果:");
    New_MidPrint(T);
    printf("\n非递归算法后序遍历的结果:");
    New_LatePrint(T);
    printf("\n\n");

    return 0;
}

根据给出的先序、中序序列画出二叉树

  • 二叉树有四个节点,先序输出序列1234,后序输出序列4321,请画出所有可能的二叉树。
    这里写图片描述

  • 一棵树的先序序列为EBADCFHGIKJ,中序序列为ABCDEFGHIJK,请画出该二叉树,并输出该二叉树的后序序列。
    这里写图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值