6-7 二叉树的非递归遍历 分数 10

news2024/11/24 3:52:59

文章目录

  • 1.非递归前序遍历
    • 1.1C++写法及解析
    • 1.2本题ac答案
  • 2.非递归中序遍历
  • 2.非递归后序遍历
    • 2.1栈模拟实现非递归
      • C++写法
      • 本题ac答案
      • 本题flag标记法
    • 2.2逆序思想
    • 2.3整体代码

在这里插入图片描述

1.非递归前序遍历

1.1C++写法及解析

vector<int> preorderTraversal(TreeNode* root)
{
    vector<int> v;       //v存储遍历结点的数据
    stack<TreeNode*> st; //st是一个栈对象 存储数据类型是结点的指针
    TreeNode* cp = root;
    while (cp || !st.empty())
    {
        //遍历到最左结点
        while (cp)
        {
            //一路记录数据作为遍历结果
            v.push_back(cp->val);
            //一路记录指针便于回溯
            st.push(cp);

            cp = cp->left;
        }

        //while循环结束 此时遍历到最左结点
        
        //栈顶结点出栈 访问栈顶结点的右子树
        TreeNode* top = st.top();
        cp = top->right;
        st.pop();
    }

    return v;
}

在这里插入图片描述

1.2本题ac答案

void PreorderTraversal(BinTree BT)
{
    Stack st = CreateStack();
    BinTree cp = BT;
    while (cp || !IsEmpty(st)) 
    {
        while (cp) 
        {
            printf(" %c", cp->Data);
            Push(st, cp);
            cp = cp->Left;
        }
        cp = Pop(st);
        cp = cp->Right;
    }
}

2.非递归中序遍历

在这里插入图片描述

void InorderTraversal(BinTree BT) 
{
    Stack st = CreateStack();
    BinTree cp = BT;
    while (cp || !IsEmpty(st))
    {
        //遍历到最左结点
        while (cp) 
        {
            //一路记录指针便于回溯
            Push(st, cp);
            cp = cp->Left;
        }
        
        //此时已到最左结点

        //假定最近一次遍历到的结点为x
        // 将x出栈 记录x指针
        // 1.将x出栈: x已在正确的顺序中被遍历 已无用
        // 2.记录x指针: 访问x数据 且 要访问x的右子树
        
        //出栈 记录指针
        cp = Pop(st);
        //访问数据
        printf(" %c", cp->Data);
        //访问右子树
        cp = cp->Right;

        //右空栈不空 还有结点待遍历 执行下一次大while循环
        //右空栈空 遍历结束
    }
}

2.非递归后序遍历

2.1栈模拟实现非递归

C++写法

vector<int> postorderTraversal(TreeNode* root)
{
    vector<int> v;
    stack<TreeNode*> st;
    TreeNode* cp = root;
    TreeNode* prv = nullptr;

    while (cp || !st.empty())
    {
        //一路遍历并记录指针到最左结点
        while (cp)
        {
            st.push(cp);
            cp = cp->left;
        }
        //while循环结束 已到最左结点 cp指向最左结点左孩子(null)
        

        对栈顶结点进行判断并处理

        TreeNode* top = st.top();
        //左已经为空 若右也空 左右已遍历结束 需要访问根
        if (top->right == nullptr || top->right == prv)
        {
            //记录当前所访问结点
            prv = top;

            //访问数据
            v.push_back(top->val);
            //出栈
            st.pop();
        }
        else
            cp = top->right;

        //cp仍指向该结点的左孩子(null)
    }

    return v;
};

本题ac答案

void PostorderTraversal(BinTree BT)
{
    Stack st = CreateStack();
    BinTree cp = BT;
    BinTree prv = NULL;

    while (cp || !IsEmpty(st))
    {
        while (cp)
        {
            Push(st, cp);
            cp = cp->Left;
        }
        BinTree top = Peek(st);
        if (top->Right == NULL || top->Right == prv)
        {
            prv = top;
            printf(" %c", top->Data);
            Pop(st);
        }
        else
            cp = top->Right;
    }
}

本题flag标记法

void PostorderTraversal(BinTree BT)
{
    if (BT == NULL)
        return;

    Stack st = CreateStack();
    BinTree cp = BT;
    cp->flag = 0;

    while (cp || !IsEmpty(st))
    {
        //一路遍历并记录指针到最左结点
        while (cp)
        {
            Push(st, cp);
            cp->flag++;//表示左子树已被遍历

            cp = cp->Left;
        }

        cp = Peek(st);
        if (cp->flag == 2)  //左右子树都被遍历
        {
            //访问
            printf(" %c", cp->Data);
            //出栈
            Pop(st);

            //神来之笔: 
            // cp置空表示当前子树已被访问完
            // 需要访问下一个栈顶即上一个结点
            cp = NULL;
        }
        else
        {
            cp->flag++;
            cp = cp->Right;
        }
    }
}

2.2逆序思想

前序遍历顺序: 根 左 右
后序遍历顺序: 左 右 根

对于正向思维 我们在上述2.1看到需要判断右子树是否已经遍历过 有两种方法:

  1. 在二叉树中结点类中加一个flag状态标记 若一个结点的左右子树都已访问 则flag == 2(实际上这种方法不建议使用 因为二叉树的有效数据应为数据域+指针域 直接在二叉树中加一个flag实在是有伤大雅)
  2. 搞一个prv指针 指向上一个访问过的top 下次访问右子树时 判断是否已访问

逆序思维是怎样的呢?

如果我们能以根 右 左的顺序遍历 最后逆序 就可以成功完成后序遍历

为什么逆序思维不用判断特殊情况?比如设置个flag或者搞一个prv?

逆序思维思想: 根先入栈 访问根 根出栈 左右子树依次入栈 此时栈中存放的结点顺序为: 左孩子 右孩子 因为栈先进后出的特性 栈顶可以先访问他的右孩子 右孩子入栈 访问右孩子 左右子树入栈…

有的同学可能就会问了那为什么不直接 正序呢? 比如: 根先不入栈 按右子树左子树的顺序入栈 这样不是可以正向输出吗?

有这样问题的同学 明显忽略了逆序思维的触发条件: 栈不空 在栈不空的条件下进行逆序操作 如果正向操作当左右子树都访问完 没办法在最后去访问根 但是逆序思维却可以在最开始访问到根 最后反转访问到的数据

class Solution
{
public:
    vector<int> postorderTraversal(TreeNode* root)
    {
        vector<int> v;
        stack<TreeNode*> st;
        //对于每一个结点: 
        // 入栈--top指向该结点--出栈-- 1. top不空--访问数据并将其左右子入栈
        //                          2. top空--不用访问数据不用将其左右子入栈
        st.push(root);

        while (!st.empty())
        {
            TreeNode* top = st.top();
            st.pop();

            if (top != nullptr)
                v.push_back(top->val);
            else
                continue;

            st.push(top->left);
            st.push(top->right);
        }

        reverse(v.begin(), v.end());

        return v;
    }
};

2.3整体代码

void InorderTraversal(BinTree BT) 
{
    Stack st = CreateStack();
    BinTree cp = BT;
    while (cp || !IsEmpty(st))
    {
        while (cp) 
        {
            Push(st, cp);
            cp = cp->Left;
        }
        cp = Pop(st);
        printf(" %c", cp->Data);
        cp = cp->Right;
    }
}
void PreorderTraversal(BinTree BT)
{
    Stack st = CreateStack();
    BinTree cp = BT;
    while (cp || !IsEmpty(st)) 
    {
        while (cp) 
        {
            printf(" %c", cp->Data);
            Push(st, cp);
            cp = cp->Left;
        }
        cp = Pop(st);
        cp = cp->Right;
    }
}
void PostorderTraversal(BinTree BT)
{
    Stack st = CreateStack();
    BinTree cp = BT;
    BinTree prv = NULL;

    while (cp || !IsEmpty(st))
    {
        while (cp)
        {
            Push(st, cp);
            cp = cp->Left;
        }
        BinTree top = Peek(st);
        if (top->Right == NULL || top->Right == prv)
        {
            prv = top;
            printf(" %c", top->Data);
            Pop(st);
        }
        else
            cp = top->Right;
    }
}

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

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

相关文章

数据结构(超详细讲解!!)第十九节 块链串及串的应用

1.定义 由于串也是一种线性表&#xff0c;因此也可以采用链式存储。由于串的特殊性&#xff08;每个元素只有一个字符&#xff09;&#xff0c;在具体实现时&#xff0c;每个结点既可以存放一个字符&#xff0c;也可以存放多个字符。每个结点称为块&#xff0c;整个链表称为块链…

linux杀毒软件ClamAV下载、安装(在线安装、离线安装)

流程图 下载 ClamAVNet 离线安装脚本 #扫描文件路径&#xff0c;程序安装路径&#xff0c;当然也可以全盘扫描&#xff0c;全盘扫描的时候路径设置为"/"即可 scanfile"/home" #分钟 小时 日 月 年, 例:0 0 * * * 表示每天0时0秒 scantime"0 0 * * *…

2023/11/2 JAVA学习

接口里面只有这两个东西,无构造器,代码块之类的 私有方法可以在接口里的其他默认方法,或私有方法中访问 静态方法,类持有,可直接调用 接口多继承,可以一个接口继承其他几个接口把几个接口合并成一个接口 先创建外部类,再创建成员内部类 在外部类中无法直接访问内部类的方法变量…

04 训练 windows环境下调用GPU资源做模型训练加速示例

笔者有一台windows电脑,要想在训练yolo模型的时候提升速度,可以按照笔者本文的示例进行。 1、检查可用GPU资源 可以在设备管理器中检查电脑中是否含有GPU设备,如下图所示,可以在设备管理器中检查显卡信息,证明我们有GPU资源可以在训练模型的时候调用。 2、核对显卡算力 …

TIME_WAIT相关知识

四次挥手 这是TCP四次握手的过程图。 TCP 连接终止时&#xff0c;主机 1 先发送 FIN 报文&#xff0c;主机 2 进入 CLOSE_WAIT 状态&#xff0c;并发送一个 ACK 应答&#xff0c;同时&#xff0c;主机 2 通过 read 调用获得 EOF&#xff0c;并将此结果通知应用程序进行主动关闭…

uniapp app端选取(上传)多种类型文件

这里仅记录本人一些遇到办法&#xff0c;后台需要file对象&#xff0c;而App端运行在jsCore内&#xff0c;并非浏览器环境&#xff0c;并没有File类&#xff0c;基本返回的都是blob路径&#xff0c;uni-file-picker得app端只支持图片和视频&#xff0c;我这边需求是音视频都要支…

浏览器请求http地址,自动跳转成https

谷歌浏览器&#xff1a; 点击url地址左侧的锁&#xff0c;选择【网站设置】 点击【隐私和安全】&#xff0c;将【不安全内容】改为允许&#xff0c;然后刷新即可

协力共创智能未来:乐鑫 ESP RainMaker 云方案线下研讨会圆满落幕

近日&#xff0c;乐鑫 ESP RainMaker 云方案线下研讨会&#xff08;深圳&#xff09;在亚马逊云科技与合作伙伴嘉宾的支持下成功举办&#xff0c;吸引了众多来自智能家电、照明电工、能源和宠物等行业的品牌客户、方案商和制造商。研讨会围绕如何基于乐鑫 ESP RainMaker 硬件连…

关于客户旅程地图:你需要知道的一切

客户旅程地图&#xff08;Customer Journey Map&#xff09;是一种工具&#xff0c;用于可视化和理解客户与品牌或产品互动的全过程。它以客户的角度展示了他们的互动&#xff0c;从最初的意识阶段到购买决策&#xff0c;再到购买和售后支持。客户旅程地图有助于企业深入了解客…

什么是物流RPA?物流RPA解决什么问题?物流RPA实施难点在哪里?

RPA指的是机器人流程自动化&#xff0c;它是一套模拟人类在计算机、平板电脑、移动设备等界面执行任务的软件。通过RPA&#xff0c;可以自动完成重复性、繁琐的工作&#xff0c;提高工作效率和质量&#xff0c;降低人力成本。RPA适用于各种行业和场景&#xff0c;例如财务、人力…

Redis基础教程

Redis基础教程 Redis介绍 官方网站&#xff1a;https://redis.io/ Redis是一种键值型的NoSql数据库&#xff0c;这里有两个关键字&#xff1a; 键值型&#xff1a;Redis中存储的数据都是以key、value对的形式存储NoSql&#xff1a;相对于传统关系型数据库而言&#xff0c;有…

关键词搜索亚马逊商品数据接口(标题|主图|SKU|价格|优惠价|掌柜昵称|店铺链接|店铺所在地)

亚马逊提供了API接口来获取商品数据。其中&#xff0c;关键词搜索亚马逊商品接口&#xff08;item_search-按关键字搜索亚马逊商品接口&#xff09;可以用于获取按关键字搜索到的商品数据。 通过该接口&#xff0c;您可以使用API Key和API Secret来认证身份&#xff0c;并使用…

Seata 四种事务模式

Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 全文参考文献&#xff1a;中文文档 TC (Transaction Coordinator) - 事务…

Redis入门指南学习笔记(2):常用数据类型解析

一.前言 本文主要介绍Redis中包含几种主要数据类型&#xff1a;字符串类型、哈希类型、列表类型、集合类型和有序集合类型。 二.字符串类型 字符串类型是Redis中最基本的数据类型&#xff0c;它是其他4种数据类型的基础&#xff0c;其他数据类型与字符串类型的差别从某种角度…

HALCON的综合应用案例【01】: 3D 算法处理在 Visual Studio 2019 C# 环境中的集成实例

前言: HALCON 为一款比较流行的商业视觉处理软件,他提供了多种开发的模式,可以在HALCON中开发,也可以将HALCON的设计通过导出库的形式集成到其他开发环境里面,以方便系统集成。本文为笔者自己的一个3D 视觉检测项目,利用HALCON的3D 库开发算法,然后,将算法集成到 MS-V…

指挥通信车360度3d虚拟互动展示系统的优势及特点

通信车是装有通信装备&#xff0c;用于保障通信联络的专用车辆&#xff0c;用于偏僻/特殊环境下的机动通信。并且机动通信局装备通常分为应急综合通信车、网络管理车、程控电话车、自适应跳频电台车、数字扩频接力车、散射通信车、卫星通信车、光缆引接车、线缆收放车和通信电源…

医疗数据可视化大屏:重构医疗决策的未来

医疗行业一直是信息密集型领域之一&#xff0c;它的复杂性不仅在于患者病历和医疗数据的海量积累&#xff0c;还包括了病情诊断、医疗资源分配、病患治疗等多层次的挑战。随着信息技术的不断发展&#xff0c;医疗数据可视化大屏成为了一种创新性的工具&#xff0c;它为医疗管理…

Linux学习笔记之一(计算机网络基础)

Linux learning note 1、计算机网络1.1、IP地址和MAC地址1.2、NAT、端口1.3、动态IP、静态IP、DHCP1.4、子网掩码、网关地址、DNS服务器1.5、TCP、UDP、ftp、http 2、虚拟机的网络管理2.1、桥接模式2.2、NAT模式2.3、仅主机模式2.4、总结 1、计算机网络 1.1、IP地址和MAC地址 …

python:将多个9波段影像tif文件转成numpy格式保存

作者:CSDN @ _养乐多_ 最近有粉丝问,如何将多个9波段的Aster影像tif文件转成numpy格式保存,然后输入网络进去训练。本文提供了两种思路和代码。 结果如下图所示, 文章目录 一、简单方法(分两步)二、端到端方法(一步到位)一、简单方法(分两步) 先将所有的多波段影像…

葡萄酒中的“多酚”有机化合物

“多酚”是在植物中发现的有机化合物&#xff0c;包括树皮、种子、坚果、茶叶和木材。单宁是一种多酚&#xff0c;它们完全是天然的&#xff0c;但是尝起来很苦。如果你是一个茶迷&#xff0c;你应该知道喝一口高单宁的红茶会使你的口腔内侧起皱。 葡萄也含有大量的单宁&#…