美文网首页
二叉树的遍历与建立

二叉树的遍历与建立

作者: lxr_ | 来源:发表于2022-08-03 21:11 被阅读0次

二叉树的遍历:

二叉树的遍历(traversing binary tree)是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。(二叉树的遍历方式可以很多,如果限制从左到右的方式,那么主要分为四种

前序遍历(根左右):

若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树,即以“根左右”的顺序进行遍历。
下图中的二叉树前序遍历(假设遍历即为输出该结点数据):
1、整棵树的根结点为A,由于前序遍历顺序为“根->左子树->右子树”,故先输出A
2、遍历左子树,其根结点为B,故输出B,此时已经得到了:AB
3、遍历左子树的左子树,其根结点为D,故输出D,此时得到:ABD
4、由于结点D没有左子树和右子树,故根结点B的左子树已经遍历完,接下来遍历其右子树
5、根结点B的右子树的根结点为E,输出E,此时得到:ABDE
6、遍历根结点E的左子树,其根结点为G,输出G,得到:ABDEG
7、遍历根结点E的右子树,其根结点为H,输出H,得到:ABDEGH
8、此时整棵子树的左子树已经遍历完成,开始遍历右子树
9、根结点A的右子树的根结点为C,故输出C,得到:ABDEGHC
10、再遍历其左子树,其根结点为F,输出F,得到:ABDEGHCF,遍历完成。
注:时刻以“根->左->右”的顺序遍历,由于根在最前,故称为前序遍历

前序遍历

中序遍历(左根右):

若二叉树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点), 中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。上图中的二叉树中序遍历结果为:DBGEHAFC

后序遍历(左右根):

若二叉树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后访问根结点。上图中的二叉树后序遍历结果为:DGHEBFCA

层序遍历:

若树为空,则空操作返回,否则从树的第一层,也就是根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。上图中的二叉树层序遍历结果为:ABCDEFGH

二叉树的建立

二叉树的建立:

如果我们要在内存中建立左图的二叉树,为了能让每个结点确认是否有左右孩子,对它进行扩展,变成右图中的样子,也就是将二叉树中每个结点的空指针引出一个虚结点,其值为一特定值,如“#”,称这种处理后的二叉树为原二叉树的扩展二叉树,扩展二叉树可以确定唯一的一棵二叉树。

扩展二叉树

代码

BiTree.h

#pragma once
#include <iostream>
#include <stack>
#include <queue>

using namespace std;

// 函数结果状态代码
#define OK      1
#define ERROR   0
#define INFEASIBLE  -1
#define OVERFLOW    -2

//Status 是函数的类型,其值是函数结果状态代码
typedef int Status;

//数据类型
typedef char TElemType;

typedef struct BiTNode
{
    TElemType data;         //结点数据
    struct BiTNode* lchild, * rchild;       //左右孩子指针


}BiTNode, * BiTree;

//遍历二叉树结点
void visit(TElemType e);

//创建二叉树
Status CreateBiTree(BiTree& T);

//前序遍历
void PreOrderTraverse(BiTree T);

//中序遍历
void InOrderTraverse(BiTree T);

//后序遍历
void PostOrderTraverse(BiTree T);

//使用栈进行遍历(中序)
void InOrderTraverseStack(BiTree T);

//层序遍历
void LeverOrderTraverse(BiTree T);

//复制二叉树
void Copy(BiTree T, BiTree& NewT);

//计算二叉树的深度
int Depth(BiTree T);

//计算二叉树结点总数
int NodeCount(BiTree T);

//计算二叉树叶子结点数
int LeafCount(BiTree T);

BiTree.cpp

#include "BiTree.h"
void visit(TElemType e)
{
    cout << e << " ";
}

Status CreateBiTree(BiTree& T)
{
    TElemType ch;
    cin >> ch;

    if (ch == '#')
    {
        T = NULL;
    }
    else
    {
        T = new BiTNode;
        if (!T)
        {
            exit(OVERFLOW);
        }
        T->data = ch;               //生成根节点

        CreateBiTree(T->lchild);    //构造左子树
        CreateBiTree(T->rchild);    //构造右子树
    }

    return OK;
}

//前序遍历
void PreOrderTraverse(BiTree T)
{
    if (T == NULL)
    {
        return;
    }

    visit(T->data);                 //根

    PreOrderTraverse(T->lchild);    //左
    PreOrderTraverse(T->rchild);    //右

}


//中序遍历
void InOrderTraverse(BiTree T)
{
    if (T == NULL)
    {
        return;
    }

    InOrderTraverse(T->lchild);     //左
    visit(T->data);                 //根
    InOrderTraverse(T->rchild);     //右
}

//后序遍历
void PostOrderTraverse(BiTree T)
{
    if (T == NULL)
    {
        return;
    }

    PostOrderTraverse(T->lchild);   //左
    PostOrderTraverse(T->rchild);   //右
    visit(T->data);                 //根
}

//层序遍历
void LeverOrderTraverse(BiTree T)
{
    queue<BiTNode> q;
    BiTNode p;

    q.push(*T);

    while (!q.empty())
    {
        visit(q.front().data);

        p = q.front();          //队头结点

        q.pop();                //出队


        if (p.lchild)           //队头结点是否有左孩子
            q.push(*(p.lchild));

        if (p.rchild)           //队头结点是否有右孩子
            q.push(*(p.rchild));

    }

}

//使用栈进行遍历(中序)
void InOrderTraverseStack(BiTree T)
{
    stack<BiTNode> s;
    BiTNode* p = T;
    //s.push(*p);

    while (p || !s.empty())
    {
        if (p)                          //如果根节点存在,则入栈
        {
            s.push(*p);
            p = p->lchild;
        }
        else                            //如果左子树为空
        {
            visit(s.top().data);        //弹栈,输出根节点
            p = s.top().rchild;     //访问右子树
            s.pop();
        }

    }
}

//复制二叉树(先序)
void Copy(BiTree T, BiTree& NewT)
{
    if (T == NULL)
    {
        NewT = NULL;
        return;
    }
    else
    {
        NewT = new BiTNode;             //创建新结点(子树)
        NewT->data = T->data;
        Copy(T->lchild, NewT->lchild);
        Copy(T->rchild, NewT->rchild);
    }

}

//计算二叉树的深度
int Depth(BiTree T)
{
    int m = 0, n = 0;
    if (T == NULL)
    {
        return 0;
    }
    else
    {
        m = Depth(T->lchild);
        n = Depth(T->rchild);

        if (m > n)
            return m + 1;
        else
            return n + 1;
    }
}


//计算二叉树结点总数
int NodeCount(BiTree T)
{
    int l = 0, r = 0;
    if (T == NULL)
    {
        return 0;
    }
    else
    {
        l = NodeCount(T->lchild);   //左子树中结点个数
        r = NodeCount(T->rchild);   //右子树中结点个数

        return l + r + 1;
    }
}

//计算二叉树叶子结点数
int LeafCount(BiTree T)
{
    int l = 0, r = 0;
    if (T == NULL)                  //空树返回0
    {
        return 0;
    }
    else
    {
        if (T->lchild == NULL && T->rchild == NULL)
        {
            return  1;              //叶子结点返回1
        }
        else
        {
            l = LeafCount(T->lchild);
            r = LeafCount(T->rchild);

            return l + r;
        }

    }
}

main.cpp

#include "BiTree.h"

#include <iostream>

using namespace std;

int main(int argc, char** argv)
{
    BiTree T;
    CreateBiTree(T);            //创建二叉树

    cout << "前序遍历:";
    PreOrderTraverse(T);        //前序遍历
    cout << endl;

    cout << "中序遍历:";
    InOrderTraverse(T);         //中序遍历
    cout << endl;

    cout << "后序遍历:";
    PostOrderTraverse(T);       //后序遍历
    cout << endl;

    cout << "层序遍历:";
    LeverOrderTraverse(T);
    cout << endl;

    cout << "非递归遍历(中序):";
    InOrderTraverseStack(T);
    cout << endl;

    BiTree NewT;
    Copy(T, NewT);              //复制二叉树T到NewT中
    cout << "层序遍历:";
    LeverOrderTraverse(NewT);
    cout << endl;

    cout << "T的深度:";
    int d = Depth(T);
    cout << d << endl;

    cout << "T中结点个数:";
    int num = NodeCount(T);
    cout << num << endl;

    cout << "T中叶子结点个数:";
    int leafNum = LeafCount(T);
    cout << leafNum << endl;

    return 0;
}

相关文章

  • 2018-12-26

    二叉树的建立与遍历

  • 记一次Tree的遍历

    统计利用先序遍历创建的二叉树的深度 利用先序递归遍历算法创建二叉树并计算该二叉树的深度。先序递归遍历建立二叉树的方...

  • 数据结构与算法二叉树的遍历与线索二叉树以及森林

    1.二叉树的遍历先序遍历、中序遍历、后序遍历 2.层次遍历利用队列实现 3.由遍历序列构成二叉树先序、后序可以与众...

  • 数据结构

    二叉树的创建与遍历

  • 二叉树的建立 建立二叉树,利用了递归的原理,也就是在打印二叉树的前中后序遍历算法中打印结点的地方,改成了生成结点,...

  • 二叉树的基本操作 - 遍历

    二叉树的基本操作 - 遍历 二叉树的遍历是非常重要的,因为我们一般对树做的很多操作基本上都是要建立在遍历的基础上的...

  • leetcode-树】从前序与中序遍历序列构造二叉树

    leetcode-树】从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树。 注意:你可以假设...

  • 数据结构题目45:二叉树的建立

    题目: 建立一棵二叉树。 解题思路:用单个字符表示二叉树中一个结点的数据,这里采用前序遍历算法。建立二叉树的过程如...

  • 二叉树 基础操作

    二叉树的使用 二叉树结构 先序创建二叉树 DFS 先序遍历二叉树 中序遍历二叉树 后序遍历二叉树 BFS 层次遍历...

  • 中序和后序遍历建立二叉树

    106. 从中序与后序遍历序列构造二叉树 根据一棵树的中序遍历与后序遍历构造二叉树。 注意:你可以假设树中没有重复...

网友评论

      本文标题:二叉树的遍历与建立

      本文链接:https://www.haomeiwen.com/subject/ujmjwrtx.html