【数据结构】树与二叉树(九):二叉树的后序遍历(非递归算法NPO)

news2024/9/21 4:40:43

文章目录

5.2.1 二叉树

  二叉树是一种常见的树状数据结构,它由结点的有限集合组成。一个二叉树要么是空集,被称为空二叉树,要么由一个根结点和两棵不相交的子树组成,分别称为左子树右子树。每个结点最多有两个子结点,分别称为左子结点和右子结点。
在这里插入图片描述

二叉树性质

引理5.1:二叉树中层数为i的结点至多有 2 i 2^i 2i个,其中 i ≥ 0 i \geq 0 i0

引理5.2:高度为k的二叉树中至多有 2 k + 1 − 1 2^{k+1}-1 2k+11个结点,其中 k ≥ 0 k \geq 0 k0

引理5.3:设T是由n个结点构成的二叉树,其中叶结点个数为 n 0 n_0 n0,度数为2的结点个数为 n 2 n_2 n2,则有 n 0 = n 2 + 1 n_0 = n_2 + 1 n0=n2+1

  • 详细证明过程见前文:【数据结构】树与二叉树(三):二叉树的定义、特点、性质及相关证明

满二叉树、完全二叉树定义、特点及相关证明

  • 详细证明过程见前文:【数据结构】树与二叉树(四):满二叉树、完全二叉树及其性质

5.2.2 二叉树顺序存储

  二叉树的顺序存储是指将二叉树中所有结点按层次顺序存放在一块地址连续的存储空间中,详见:
【数据结构】树与二叉树(五):二叉树的顺序存储(初始化,插入结点,获取父节点、左右子节点等)

5.2.3 二叉树链接存储

  二叉树的链接存储系指二叉树诸结点被随机存放在内存空间中,结点之间的关系用指针说明。在链式存储中,每个二叉树结点都包含三个域:数据域(Data)、左指针域(Left)和右指针域(Right),用于存储结点的信息和指向子结点的指针,详见:
【数据结构】树与二叉树(六):二叉树的链式存储

5.2.4 二叉树的遍历

  • 遍历(Traversal)是对二叉树中所有节点按照一定顺序进行访问的过程。
  • 通过遍历,可以访问树中的每个节点,并按照特定的顺序对它们进行处理。
  • 对二叉树的一次完整遍历,可给出树中结点的一种线性排序。
    • 在二叉树中,常用的遍历方式有三种:先序遍历中序遍历后序遍历
    • 这三种遍历方式都可以递归地进行,它们的区别在于节点的访问顺序
      • 在实现遍历算法时,需要考虑递归终止条件和递归调用的顺序。
    • 还可以使用迭代的方式来实现遍历算法,使用栈或队列等数据结构来辅助实现。
  • 遍历是二叉树中基础而重要的操作,它为其他许多操作提供了基础,如搜索、插入、删除等。
    在这里插入图片描述

1-3 先序、中序、后序遍历递归实现及相关练习

【数据结构】树与二叉树(七):二叉树的遍历(先序、中序、后序及其C语言实现)

后序遍历递归实现

void postOrderTraversal(struct Node* root) {
    if (root == NULL) {
        return;
    }
    // 递归遍历左子树
    postOrderTraversal(root->left);
    // 递归遍历右子树
    postOrderTraversal(root->right);
    // 访问根节点
    printf("%c ", root->data);
}

4. 中序遍历非递归

【数据结构】树与二叉树(八):二叉树的中序遍历(非递归算法NIO)

5. 后序遍历非递归

a. 算法NPO

NPO

b. 算法解读

  算法NPO(t)利用了一个辅助堆栈S来遍历二叉树T的所有节点。

  1. 如果t为空,则直接返回。
  2. 创建一个空堆栈S,并将根节点t和初始标记0入栈(S <= (t, 0))。
  3. 进入循环,只要堆栈S非空,执行以下步骤:
    a. 从堆栈S中弹出栈顶元素,将其赋值给(p, i)。
    b. 如果标记i为0,则表示节点p还未处理左子树,将左子节点入栈(S <= (Left( p), 0))。
    c. 如果标记i为1,则表示节点p已处理完左子树,但还未处理右子树,将右子节点入栈(S <= (Right( p), 0))。
    d. 如果标记i为2,则表示节点p的左右子树都已处理完毕,可以打印节点p的值。
  4. 跳转到步骤3,继续循环,直到堆栈S为空。

c. 典例剖析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

d.代码实现

void nonRecursiveInOrder(struct Node* root) {
    struct Node* stack[100];  // 辅助堆栈,用于模拟递归调用栈
    int top = -1;  // 栈顶指针

    struct Node* current = root;

    while (current != NULL || top != -1) {
        // 将当前结点的左子结点入栈
        while (current != NULL) {
            stack[++top] = current;
            current = current->left;
        }

        // 弹出栈顶结点,并访问
        current = stack[top--];
        printf("%c ", current->data);

        // 处理右子结点
        current = current->right;
    }
}

5. 代码整合

#include <stdio.h>
#include <stdlib.h>

// 二叉树结点的定义
struct Node {
    char data;
    struct Node* left;
    struct Node* right;
};

// 创建新结点
struct Node* createNode(char data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    if (newNode == NULL) {
        printf("Memory allocation failed!\n");
        exit(1);
    }
    newNode->data = data;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}

// 后序遍历
void postOrderTraversal(struct Node* root) {
    if (root == NULL) {
        return;
    }
    // 递归遍历左子树
    postOrderTraversal(root->left);
    // 递归遍历右子树
    postOrderTraversal(root->right);
    // 访问根节点
    printf("%c ", root->data);
}


// 非递归后根遍历
void nonRecursivePostOrder(struct Node* root) {
    struct Node* stack[100];  // 辅助堆栈,用于模拟递归调用栈
    int tagStack[100];  // 标记堆栈,用于记录结点的访问状态
    int top = -1;  // 栈顶指针

    struct Node* current = root;
    int tag = 0;

    while (current != NULL || top != -1) {
        while (current != NULL && tag == 0) {
            stack[++top] = current;
            tagStack[top] = 0;
            current = current->left;
        }

        if (tagStack[top] == 0) {
            current = stack[top];
            tagStack[top] = 1;
            current = current->right;
            tag = 0;
        } else if (tagStack[top] == 1) {
            current = stack[top--];
            printf("%c ", current->data);
            tag = 1;
        }
    }
}

int main() {
    // 创建一棵二叉树
    struct Node* root = createNode('a');
    root->left = createNode('b');
    root->right = createNode('c');
    root->left->left = createNode('d');
    root->left->right = createNode('e');
    root->left->right->left = createNode('f');
    root->left->right->right = createNode('g');

    // 递归后序遍历二叉树
    printf("Recursive In-order traversal: \n");
    postOrderTraversal(root);
    printf("\n");


    // 非递归后序遍历二叉树
    printf("Non-recursivePost-order traversal: \n");
    nonRecursivePostOrder(root);
    printf("\n");
    
    return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1193763.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【考研数据结构代码题4】求树中度为1的结点数(递归方式)

题目&#xff1a;用C语言描述树的孩子兄弟链表结构&#xff0c;并编写递归程序求树中度为1的结点数 难度&#xff1a;★★ 算法思路&#xff1a;递归地遍历当前结点的左孩子子树与右兄弟子树&#xff0c;分别求二者中度为1的结点数记为h1,h2,若当前结点仅有1个结点&#xff0c;…

好用的vscode插件

一、代码管理 git GitLens — Git supercharged Git History gitignore 项目管理 Project Manager 管理多个项目 Todo Tree 快速定位代码中的todo WakaTime 用于在编程活动中自动统计工作量、代码提交和时间跟踪等 VS Code Counter 该插件用于帮助我们统计项目代码的行数…

防火墙部署模式 -- 单臂路由模式

防火墙单臂路由部署模式 如图&#xff0c;PC 1与PC 2通信&#xff0c;想在中间加上防火墙对其进行监控&#xff0c;并实现对两台设备的通信阻断&#xff0c;可以在交换机的另一个接口上连接防火墙&#xff0c;交换机将两台PC发送的数据引流到防火墙上&#xff0c;防火墙也配置下…

virtualBox虚拟机局域网访问配置

在VirtualBox中&#xff0c;桥接网络是一种网络连接类型&#xff0c;它允许虚拟机连接到物理网络上的路由器或交换机&#xff0c;在物理网络上获得独立的网络地址和访问权限。 一、设置VirtualBox桥接网络的步骤&#xff1a; 打开VirtualBox软件&#xff0c;并选择你想要配置…

P1547 [USACO05MAR] Out of Hay S 题解

文章目录 题目描述输入格式输出格式样例样例输入样例输出 完整代码 题目描述 Bessie 计划调查 N N N&#xff08; 2 ≤ N ≤ 2 000 2 \leq N \leq 2\,000 2≤N≤2000&#xff09;个农场的干草情况&#xff0c;它从 1 1 1 号农场出发。农场之间总共有 M M M&#xff08; 1 ≤…

Matlab导出高清图片方法

一、背景 使用matlab绘制图片后&#xff0c;需要将图片导出为.jpg或.eps格式以便后期使用。但通过文件–另存为.jpg时&#xff0c;并没有清晰度选择&#xff0c;导出的图片只有30几k&#xff0c;以至于图片很模糊。 二、Matlab导出高清图片方法 文件—导出设置 1、大小&…

kubernetes etcd

目录 一、备份 二、回复 官网&#xff1a; https://v1-25.docs.kubernetes.io/zh-cn/docs/tasks/administer-cluster/configure-upgrade-etcd/#restoring-an-etcd-cluster 一、备份 从镜像中拷贝etcdctl二进制命令 输入ctrlpq快捷键&#xff0c;把容器打入后台 docker run…

opencv dnn模块 示例(22) 目标检测 object_detection 之 yolov7

在YOLOv6 初版出来不久&#xff0c;YOLOv7就立马横空出世了。与YOLOv5、YOLOv6不同&#xff0c;YOLOv7是由YOLOv4团队的原班人马提出的&#xff08;官方出品&#xff09;。从论文的表上来看&#xff0c;目前YOLOv7无论是在实时性还是准确率上都已经超过了当时已知的所有目标检测…

【二叉树】如何构建一个包含大量随机数节点的二叉树测试用例

【二叉树】如何构建一个包含大量随机数节点的二叉树测试用例 前言一、案例准备二、自动生成随机二叉树工具类&#xff08;TreegenerateUtils&#xff09;三、如何调用随机二叉树工具类&#xff08;TreegenerateUtils&#xff09;&#xff1f; 前言 今天笔者在测试有关二叉树的…

打开ps提示,计算机中丢失d3dcompiler_47.dll怎么解决?

“d3dcompiler_47.dll丢失5个解决办法”。相信很多同事在工作或者娱乐的过程中&#xff0c;都遇到过这个错误提示。那么&#xff0c;究竟什么是d3dcompiler_47.dll文件&#xff1f;为什么会丢失呢&#xff1f;又该如何解决这个问题呢&#xff1f;接下来&#xff0c;我将为大家详…

财税服务展示预约小程序的作用是什么

财税财政往往困扰着很多公司&#xff0c;尤其是公司里没有相应职员或工作压力大的情况下&#xff0c;不少商家就会寻找代理记账、审计服务、会计代理等服务的机构。 对财政服务代理机构&#xff08;会计公司&#xff09;来说&#xff0c;市场企业多而广&#xff0c;理论上来说…

yolov5 利用Labelimg对图片进行标注

首先打开yolov5-master&#xff0c;在data文件中新建一个文件夹来存放你需要跑的数据&#xff0c;例如我这次跑的是羽毛球&#xff0c;文件把文件取名为badminton。使用其他文件夹例如images也可以&#xff0c;就是跑多了以后不好整理&#xff0c;然后点击 选中刚刚你存放数据的…

【算法 | 数论 No.1】AcWing1246. 等差数列

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【AcWing算法提高学习专栏】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&a…

c: struct sort descending and ascending in windows and Ubuntu

/*** file StudentStructSort.h* author geovindu,Geovin Du,涂聚文 (geovindu163.com)* ide: vscode c11,c17 Ubuntu 22.4* brief 结构体排序示例* date 2023-11-05* version 0.1* copyright geovindu 站在巨人的肩膀上 Standing on the Shoulders of Giants**/#ifnd…

easyexcel==省市区三级联动

省市区三级联动&#xff0c;不选前面的就没法选后面的 package com.example.demoeasyexcel.jilian2; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import org.apache.poi.ss.use…

​软考-高级-系统架构设计师教程(清华第2版)【第2章 计算机系统基础知识-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第2章 计算机系统基础知识-思维导图】 课本里章节里所有蓝色字体的思维导图

MySQL | 查询接口性能调优、编码方式不一致导致索引失效

背景 最近业务反馈&#xff0c;列表查询速度过慢&#xff0c;需要优化。 到正式环境系统去验证&#xff0c;发现没筛选任何条件的情况下&#xff0c;查询需要三十多秒&#xff0c;而筛选了条件之后需要13秒。急需优化。 先说结论&#xff1a;连表用的字段编码方式不一致导致索…

【异常----finally和自定义异常】

文章目录 finally练习问题 异常的处理流程【异常处理流程总结】自定义异常类 finally 有些特定的代码&#xff0c;不论程序是否发生异常&#xff0c;都需要执行&#xff0c;比如程序中打开的资源&#xff1a;在程序正常或者异常退出时&#xff0c;必须要对资源进进行回收。另外…

Halcon Variable Inspect 安装失败

版本 Visual Studio 2022Halcon 20.11 找到Halcon 扩展文件 输入CMD 经过下面博客所示步骤&#xff0c;修改Visual Studio 对应版本 Halcon Variable Inspect 安装失败 替换成功&#xff01;

混淆矩阵和相应参数详解

如果一个模型在能够尽量捕获少数类的情况下&#xff0c;还能够尽量对多数类判断正确&#xff0c;则这个模型就非常优秀了。为了评估这样的能力&#xff0c;我们将引入新的模型评估指标&#xff1a;混淆矩阵和ROC曲线。 上面是混淆矩阵。接下来我们结合图像解释一下准确率&#…