【树】建立二叉链表存储的二叉树+遍历二叉树(先序、中序、后序、层序)

这篇具有很好参考价值的文章主要介绍了【树】建立二叉链表存储的二叉树+遍历二叉树(先序、中序、后序、层序)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

建立二叉链表存储的二叉树+遍历二叉树(先序、中序、后序、层序)

1.建立二叉链表存储的二叉树

1-1.原理

二叉树的构建利用了递归的原理,在按先序序列构建二叉树时,为了能让电脑知道每个结点是否有左右孩子,我们要对原二叉树进行扩展,明确表示每个结点的左右孩子,若当前结点没有左右孩子,我们用’#'表示。
由普通二叉树---->扩展二叉树,如下图:
【树】建立二叉链表存储的二叉树+遍历二叉树(先序、中序、后序、层序)
此时当我们按先序序列构建上面的二叉树时,应输入的序列为:AB#D##C##

1-2.代码

void CreateBiTree(BiTree *T)  // 二叉树的构造
{
    char ch;
    scanf("%c", &ch);

    if (ch == '#')  *T = NULL;                   // #表示当前结点为空
    else {
        *T = (BiTree)malloc(sizeof(BiTNode));    // 动态申请结点内存
        (*T)->data = ch;                         // 生成根结点
        CreateBiTree(&(*T)->lchild);             // 构造左子树
        CreateBiTree(&(*T)->rchild);             // 构造右子树
    }
}

1-3.实例

以下图的二叉树为例:(后面的实例均以该二叉树为例
【树】建立二叉链表存储的二叉树+遍历二叉树(先序、中序、后序、层序)

#include <iostream>
using namespace std;

const int N = 100;

typedef struct  BiTNode
{
    char data;
    BiTNode *lchild;
    BiTNode *rchild;
} BiTNode, *BiTree;

void CreateBiTree(BiTree *T)  // 建立二叉链表存储的二叉树
{
    char ch;
    scanf("%c", &ch);

    if (ch == '#')  *T = NULL;                   // #表示当前结点为空
    else {
        *T = (BiTree)malloc(sizeof(BiTNode));    // 动态申请结点内存
        (*T)->data = ch;                         // 生成根结点
        printf("%c", (*T)->data);                // 检验建立的顺序
        CreateBiTree(&(*T)->lchild);             // 构造左子树
        CreateBiTree(&(*T)->rchild);             // 构造右子树
    }
}


int main()
{
    BiTree T;
    CreateBiTree(&T);
    return 0;
}

2.先序遍历

2-1.递归

若二叉树为空,则返回;否则先访问根结点,然后先序遍历左子树,最后先序遍历右子树。

void PreOrderTraverse(BiTree T)    // 先序遍历二叉树
{
    if (T == NULL)  return;
    printf("%c", T->data);        // 先显示结点数据
    PreOrderTraverse(T->lchild);  // 再先序遍历左子树
    PreOrderTraverse(T->rchild);  // 最后先序遍历右子树
}

2-2.非递归

用栈来实现:
(1)首先访问根结点,根节点入栈并进去其左子树,然后访问左子树的根节点,入栈并进入下一层的左子树,直到当前结点为空。
(2)若栈此时非空,则从栈中退出栈顶元素,进入该结点的右子树。
重复(1)(2),直到当前结点和栈都是空的,结束。

void PreOrder(BiTree T)    // 先序遍历二叉树(非递归)
{
    BiTNode *s[N];    // 用结构体指针数组模拟栈
    int top = 0;      // 设置栈顶指针
    BiTNode *p;
    p = T;
    while (top != 0 || p != NULL) {   // 若当前结点为空结点 且 栈为空,则结束
        while (p != NULL) {   // 若当前结点不为空,则访问根结点,根指针入栈,进入左子树
            printf("%c", p->data);
            s[++top] = p;
            p = p->lchild;
        }
        if (top != 0) {   // 若栈不为空,根指针退栈,进入其右子树
            p = s[top--];
            p = p->rchild;
        }
    }
}

2-3.实例

测试输入:ab#d##c##
测试输出:abdc

#include <iostream>
using namespace std;

const int N = 100;

typedef struct BiTNode
{
    char data;
    BiTNode *lchild;
    BiTNode *rchild;
} BiTNode, *BiTree;

void CreateBiTree(BiTree *T)  // 建立二叉链表存储的二叉树
{
    char ch;
    scanf("%c", &ch);

    if (ch == '#')  *T = NULL;                   // #表示当前结点为空
    else {
        *T = (BiTree)malloc(sizeof(BiTNode));    // 动态申请结点内存
        (*T)->data = ch;                         // 生成根结点
        CreateBiTree(&(*T)->lchild);             // 构造左子树
        CreateBiTree(&(*T)->rchild);             // 构造右子树
    }
}

void PreOrderTraverse(BiTree T)   // 先序遍历二叉树(递归)
{
    if (T == NULL)  return;
    printf("%c", T->data);
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);
}

void PreOrder(BiTree T)    // 先序遍历二叉树(非递归)
{
    BiTree s[N];
    int top = 0;
    BiTree p;
    p = T;
    while (p != NULL || top != 0) {    // 若当前结点非空,或者栈不为空
        while (p != NULL) {   // 依次访问左子树,并入栈
            printf("%c", p->data);  
            s[++top] = p;
            p = p->lchild;
        }
        if (top != 0) {    // 返回栈顶元素,及当前结点的根节点,并进入根节点的右子树
            p = s[top--];
            p = p->rchild;
        }
    }
}

int main()
{
    BiTree T;
    CreateBiTree(&T);
    PreOrderTraverse(T);
    printf("\n");
    PreOrder(T);
    return 0;
}

3.中序遍历

3-1.递归

若二叉树为空,则返回;否则先中序遍历左子树,然后访问根结点,最后中序遍历右子树。

void InOrderTraverse(BiTree T)
{
    if (T == NULL)  return;
    InOrderTraverse(T->lchild);
    printf("%c", T->data);
    InOrderTraverse(T->rchild);
}

3-2.非递归

用栈实现:
(1)根结点入栈,进入其左子树,进而左子树的根结点入栈,进入下一层的左子树,直到当前结点为空。
(2)若栈不为空,从栈顶退出上一层的结点,访问此结点,并进入该结点的右子树。
重复执行(1)(2),直到当前结点和栈均为空,结束。

void InOrder(BiTree T)    // 中序遍历二叉树(非递归)
{
    BiTNode *s[N];    // 用结构体指针数组模拟栈
    int top = 0;      // 设置栈顶指针
    BiTNode *p;
    p = T;
    while (top != 0 || p != NULL) {   // 若当前结点为空结点 且 栈为空,则结束
        while (p != NULL) {   // 若当前结点不为空,则访问根结点,根指针入栈,进入左子树
    
            s[++top] = p;
            p = p->lchild;
        }
        if (top != 0) {   // 若栈不为空,根指针退栈,进入其右子树
            p = s[top--];
            printf("%c", p->data);   // 先访问完左结点之后,回到根结点,再访问根节点
            p = p->rchild;
        }
    }
}

3-3.实例

测试输入:ab#d##c##
测试输出:bdac

#include <iostream>
using namespace std;

const int N = 100;

typedef struct BiTNode   // 二叉树的结点结构
{
    char data;   // 结点数据
    BiTNode *lchild;
    BiTNode *rchild; // 左右孩子指针
} BiTNode, *BiTree;

void CreateBiTree(BiTree *T)  // 建立二叉链表存储的二叉树
{
    char ch;
    scanf("%c", &ch);

    if (ch == '#')  *T = NULL;                   // #表示当前结点为空
    else {
        *T = (BiTree)malloc(sizeof(BiTNode));    // 动态申请结点内存
        (*T)->data = ch;                         // 生成根结点
        CreateBiTree(&(*T)->lchild);             // 构造左子树
        CreateBiTree(&(*T)->rchild);             // 构造右子树
    }
}


void InOrderTraverse(BiTree T)    // 中序遍历二叉树(递归)
{
    if (T == NULL)  return;
    InOrderTraverse(T->lchild);  // 先中序遍历左子树
    printf("%c", T->data);        // 再显示结点数据
    InOrderTraverse(T->rchild);  // 最后中序遍历右子树
}

void InOrder(BiTree T)    // 中序遍历二叉树(非递归)
{
    BiTNode *s[N];    // 用结构体指针数组模拟栈
    int top = 0;      // 设置栈顶指针
    BiTNode *p;
    p = T;
    while (top != 0 || p != NULL) {   // 若当前结点为空结点 且 栈为空,则结束
        while (p != NULL) {   // 若当前结点不为空,则访问根结点,根指针入栈,进入左子树
    
            s[++top] = p;
            p = p->lchild;
        }
        if (top != 0) {   // 若栈不为空,根指针退栈,进入其右子树
            p = s[top--];
            printf("%c", p->data);   // 先访问完左结点之后,回到根结点,再访问根节点
            p = p->rchild;
        }
    }
}

int main()
{
    BiTree T;
    CreateBiTree(&T);

    InOrderTraverse(T);
    printf("\n");
    InOrder(T);

    return 0;
}

4.后序遍历

4-1.递归

若二叉树为空,则返回;否则先后序遍历左子树,然后访问根结点,最后后序遍历右子树。

void PostOrderTraverse(BiTree T)
{
    if (T == NULL)  return;
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    printf("%c", T->data);
}

4-2.非递归

同样用栈来实现:
(1)根结点入栈,进入其左子树,进而左子树的根结点入栈,进入下一层左子树,直到当前结点为空。
(2)若栈非空,如果栈顶结点p的右子树为空或者已经被访问过,则退出栈,访问p结点,并将p赋值给q,p置为空;如果栈顶结点有右子树且未被访问,则进入p的右子树。
重复执行(1)(2),直到当前结点和栈均为空,结束。


void PostOrder(BiTree T)   // 后序遍历二叉树(非递归)
{
    BiTNode *s[N];
    int top = 0;
    BiTNode *p, *q;  // q存储刚刚访问过的结点,p存储当前根结点
    p = T;
    q = NULL;
    while (p != NULL || top != 0) {
        while (p != NULL) {
            s[++top] = p;
            p = p->lchild;
        }
        if (top != 0) {
            p = s[top];   // 获取栈顶元素
            if (p->rchild == NULL || p->rchild == q) {  // 若右子树为空 或者 右子树刚刚被访问过
                top--;   // 栈顶元素出栈
                printf("%c", p->data);
                q = p;  
                p = NULL; 
            }
            else {
                p = p->rchild;
            }
        }
    }
}

4-3.实例

测试输入:ab#d##c##
测试输出:dbca

#include <iostream>
using namespace std;

const int N = 100;

typedef struct BiTNode   // 二叉树的结点结构
{
    char data;   // 结点数据
    BiTNode *lchild, *rchild;   // 左右孩子指针
} BiTNode, *BiTree;

void CreateBiTree(BiTree *T)    // 建立二叉链表存储的二叉树
{
    char ch;
    scanf("%c", &ch);

    if (ch == '#')  *T = NULL;                   // #表示当前结点为空
    else {
        *T = (BiTree)malloc(sizeof(BiTNode));    // 动态申请结点内存
        (*T)->data = ch;                         // 生成根结点
        CreateBiTree(&(*T)->lchild);             // 构造左子树
        CreateBiTree(&(*T)->rchild);             // 构造右子树
    }
}

void PostOrderTraverse(BiTree T)   // 后序遍历二叉树(递归)
{
    if (T == NULL)  return;
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    printf("%c", T->data);
}

void PostOrder(BiTree T)   // 后序遍历二叉树(非递归)
{
    BiTNode *s[N];
    int top = 0;
    BiTNode *p, *q;  // q存储刚刚访问过的结点,p存储当前根结点
    p = T;
    q = NULL;
    while (p != NULL || top != 0) {
        while (p != NULL) {
            s[++top] = p;
            p = p->lchild;
        }
        if (top != 0) {
            p = s[top];   // 获取栈顶元素
            if (p->rchild == NULL || p->rchild == q) {  // 若右子树为空 或者 右子树刚刚被访问过
                top--;   // 栈顶元素出栈
                printf("%c", p->data);
                q = p;  
                p = NULL; 
            }
            else {
                p = p->rchild;
            }
        }
    }
}

int main()
{
    BiTree T;
    CreateBiTree(&T);

    PostOrderTraverse(T);
    printf("\n");
    PostOrder(T);

    return 0;
}

5.层序遍历

5-1.层序遍历代码

层序遍历用队列来实现,首先根结点入队,当队列非空时,重复执行下面两个操作:
(1)队头结点出队,访问出队结点。
(2)出队结点的非空左右孩子入队。

void LevelOrder(BiTree T)   // 二叉树的层序遍历
{
    BiTNode *Q[N];   // 数组模拟队列
    int front = 0;
    int rear = 0;
    BiTNode *p;

    Q[++rear] = T;  // 根结点入队
    while (front != rear) {   // 若队列不为空
        // 队头结点出队,并访问出队结点
        p = Q[++front];
        printf("%c", p->data);
        // 出队结点的非空左右孩子依次入队
        if (p->lchild != NULL) {
            Q[++rear] = p->lchild;
        }
        if (p->rchild != NULL) {
            Q[++rear] = p->rchild;
        }
    }
}

5-2.实例

测试输入:ab#d##c##
测试输出:abcd

#include <iostream>
using namespace std;

const int N = 100;

typedef struct BiTNode
{
    char data;
    BiTNode *lchild;
    BiTNode *rchild;
} BiTNode, *BiTree;

void CreateBiTree(BiTree *T)  // 建立二叉链表存储的二叉树
{
    char ch;
    scanf("%c", &ch);

    if (ch == '#')  *T = NULL;                   // #表示当前结点为空
    else {
        *T = (BiTree)malloc(sizeof(BiTNode));    // 动态申请结点内存
        (*T)->data = ch;                         // 生成根结点
        CreateBiTree(&(*T)->lchild);             // 构造左子树
        CreateBiTree(&(*T)->rchild);             // 构造右子树
    }
}

void LevelOrder(BiTree T)   // 二叉树的层序遍历
{
    BiTNode *Q[N];   // 数组模拟队列
    int front = 0;
    int rear = 0;
    BiTNode *p;

    Q[++rear] = T;  // 根结点入队
    while (front != rear) {   // 若队列不为空
        // 队头结点出队,并访问出队结点
        p = Q[++front];
        printf("%c", p->data);
        // 出队结点的非空左右孩子依次入队
        if (p->lchild != NULL) {
            Q[++rear] = p->lchild;
        }
        if (p->rchild != NULL) {
            Q[++rear] = p->rchild;
        }
    }
}

int main()
{
    BiTree T;

    CreateBiTree(&T);
    LevelOrder(T);
    
    return 0;
}

内容参考:
《大话数据结构》 程杰
《数据结构与算法》王曙燕文章来源地址https://www.toymoban.com/news/detail-465317.html

到了这里,关于【树】建立二叉链表存储的二叉树+遍历二叉树(先序、中序、后序、层序)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 根据二叉树的先序、中序、后序遍历构建二叉树-图文详解

    引言:根据一颗二叉树,可以得出他的先序、中序、后序三种遍历方式,那么如果我们知道了他的前序、中序、后序遍历,如何绘制出这颗二叉树呢? 特性A,对于前序遍历,第⼀个肯定是根节点; 特性B,对于后序遍历,最后⼀个肯定是根节点; 特性C,利⽤前序或后序遍历

    2024年02月06日
    浏览(31)
  • 二叉树的先序、中序、后序遍历C++

    二叉树的节点结构如下所示 如下所示是一个二叉树,其中的每一个节点都是由上述TreeNode节点的一个具体对象。                                 图1 先遍历根(父)节点 、再遍历左节点、最后遍历右节点。 注意:这里说的遍历并不是行走。毕竟我们能够先取到的指针只

    2024年02月15日
    浏览(24)
  • 【数据结构】二叉树的创建和遍历(先序、中序、后序)

    最近一段时间学习了数据结构中二叉树的基本操作,包括二叉树的结构、二叉树的创建、递归先序中序后序遍历、非递归遍历等,想着把二叉树的相关知识和自己的见解放到网上来让网友看看是否正确,想和网友一起共同交流。 先了解一下二叉树的三个基本性质: 性质1:在

    2024年02月04日
    浏览(35)
  • 数据结构——二叉树先序、中序、后序三种遍历

    先序遍历可以想象为,一个小人从一棵二叉树根节点为起点,沿着二叉树外沿,逆时针走一圈回到根节点,路上遇到的元素顺序,就是先序遍历的结果 先序遍历结果为:A B D H I E J C F K G 动画演示: 记住小人沿着外围跑一圈(直到跑回根节点),多看几次动图便能理解    

    2024年02月11日
    浏览(42)
  • C语言完整代码实现:二叉树的先序遍历、中序遍历、后序遍历

    一、先序遍历原理        先序遍历就是: 根、左、右 ,也就是先遍历根结点再遍历左结点最后再遍历右结点,注意:如果遍历到的结点不是叶子结点的话需要对该结点进行拆分,比如这棵二叉树: 先遍历 A ,然后是 B ,然后再是 C ,但是由于B并不是叶子结点,他本身又是

    2024年02月07日
    浏览(35)
  • 二叉树的遍历(先序遍历,中序遍历,后序遍历)递归与非递归算法

    先序遍历:先遍历一颗树的根节点,后遍历左子树,最后遍历右子树     先序遍历序列: 1 - 2 - 4 - 5 - 3 - 6 - 7 分解子问题方法 思路:将一颗二叉树看做两个部分,一个部分是左路节点,另一个部分是左路节点的右子树,先将二叉树的左路节点全部入栈,再依次出栈,出栈的

    2024年02月14日
    浏览(27)
  • 二叉树先序,中序,后序遍历的非递归算法(一)

    思路: 二叉树的前序遍历过程: 从树根开始沿着左子树一直深入,直到最左端无法深入时,返回; 进入最近深入时遇到结点的右子树,再进行如此的深入和返回; 直到最后从根节点的右子树返回到根节点为止; 由其深入返回的过程我们知道可以用一个栈来帮助我们消除递

    2023年04月14日
    浏览(67)
  • 递归和迭代实现二叉树先序、中序、后序和层序遍历

    递归比较简单,直接上代码: ### 1.1 先序遍历 1.2 中序遍历 1.3 后序遍历 能够用递归方法解决的问题基本都能用非递归方法实现。因为递归方法无非是利用函数栈来保存信息,可以寻找相应的数据结构替代函数栈,同样可以实现相同的功能。下面用栈,类比递归方法来统一实

    2024年01月20日
    浏览(27)
  • 十三、数据结构——二叉树的遍历(先序、中序和后序)详细思路和代码

    在数据结构中,二叉树是一种常用且重要的数据结构。二叉树的遍历是指按照一定顺序访问二叉树的所有节点,常见的遍历方式有前序遍历、中序遍历和后序遍历。本文将详细介绍这三种遍历算法,并介绍最优二叉树。 首先,我们先来了解一下二叉树的基本定义。二叉树是每

    2024年02月15日
    浏览(30)
  • 假设二叉树中每个结点值为单个字符,采用二叉链存储结构存储。设计一个算法,求二叉树b中第k层上叶子结点个数(非递归算法)。

    int LevelCount(BiTNode *b,int k){         BiTNode *p=b,*temp[Maxsize];         int layer=0,count=0, m=0, n=1; (m: 上一层结点的尾   n: 当层结点的尾 )         temp[0]=NULL;         temp[1]=p;         if(p==NULL) return 0;// 二叉树为空,任意层结点个数均为 0         while(1){          

    2024年02月04日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包