树(Tree)——(二)链式存储

2023-11-13

用代码实现前序、中序、后序,第一种方法就是使用递归,另一种是使用栈。将分别讲述。

目录

1. 递归实现

main函数(C语言版本)

2. 利用栈实现

mystack.h

mystack.cpp

main函数

3.补充:求树高度的函数


 

 

1. 递归实现

main函数(C语言版本)

#include <stdio.h>

#if 0  //如下图示意图的树
                  a1
         b2             c3
     d4     e5              f6

前中后序如下
preOrder : 1 2 4 5 3 6 中左右
midOrder : 4 2 5 1 3 6 左中右
postOrder: 4 5 2 6 3 1 左右中;

#endif
//先中后,三种遍历的方式,本质是压栈顺序是没有什么不同的,
//所谓先中后,无非是访问根节点的时机不同而已。

typedef struct _TreeNode  //二叉树的结构体
{
        int _data;
        struct _TreeNode *_left;
        struct _TreeNode *_right;
}TreeNode;


void preOrderTraverse(TreeNode* r)  //先序遍历
{
    if(r)
    {
        printf("%d ",r->_data);            //根左右
        preOrderTraverse(r->_left);   //递归,每个节点,都是独立的树,需要再次先序遍历,代码较少,但是思考是需要些时间的
        preOrderTraverse(r->_right);
    }
}

void middleOrderTraverse(TreeNode* r)  //中序遍历
{
    if(r)
    {
        middleOrderTraverse(r->_left);   //左根右
        printf("%d ",r->_data);
        middleOrderTraverse(r->_right);
    }
}

void postOrderTraverse(TreeNode* r)  //后序遍历
{
    if(r)
    {
        postOrderTraverse(r->_left);   //左右根
        postOrderTraverse(r->_right);
        printf("%d ",r->_data);
    }
}

int main()
{
    TreeNode a,b,c,d,e,f;    //画树
    TreeNode * root = &a;
    a._data=1;b._data=2;c._data=3;
    d._data=4;e._data=5;f._data=6;
    a._left=&b;a._right=&c;
    b._left=&d;b._right=&e;
    c._left=NULL; c._right=&f;
    d._left=d._right=e._left=e._right=f._left=f._right=NULL;

    preOrderTraverse(root);
    putchar(10);
    middleOrderTraverse(root);
    putchar(10);
    postOrderTraverse(root);
    return 0;
}

 

2. 利用栈实现

这里需要栈的定义和函数

mystack.h

#include<stdio.h>
#include<stdlib.h>
typedef struct _TreeNode
{
        int _data;
        struct _TreeNode *_left;
        struct _TreeNode *_right;
}TreeNode;

typedef struct _Node
{
        TreeNode* data;  //变量改成TreeNode*
        struct _Node* next;
}Node;

typedef struct _Stack
{
        Node* top;
}Stack;

void initStack(Stack *s);         //先初始化
int isStackEmpty(Stack *s);//判断是否为空
void push(Stack *s, TreeNode *ch); //往里压
TreeNode* pop(Stack *s);                //往外弹
void resetStack(Stack*s);      //复位
void destroyStack(Stack*s);  //销毁

mystack.cpp

#include"mystack.h"
void initStack(Stack *s)         //初始化
{
    s->top=(Node*)malloc(sizeof(Node)); 
    s->top->next=NULL;
}

int isStackEmpty(Stack *s)//判断是否为空
{
    return s->top->next==NULL; 
}

void push(Stack *s, TreeNode* ch) //往里压
{
    Node *cur=(Node*)malloc(sizeof(Node));
    cur->data=ch;
    cur->next=s->top->next;    //链表的头插法
    s->top->next=cur;
}

TreeNode * pop(Stack *s)                //往外弹
{
    Node*t=s->top->next;       //找一个替身
    s->top->next=t->next;       //把头节点后面的首节点拿下来,实现先进后出,后进先出
    TreeNode * ch;
    ch=t->data;               //因为要释放 t ,而且需要返回char,所以创建个变量记录下
    free(t);
    return ch;
}

void resetStack(Stack*s)  //复位
{
    while(!isStackEmpty( s))//一直弹出就行,pop函数里已经有释放
        pop(s);
}

void destroyStack(Stack*s)  //销毁
{
    resetStack(s);
    free(s->top);
}

 

main函数

#include <stdio.h>
#include"mystack.h"

#if 0
                  a1
         b2             c3
     d4     e5              f6

前中后序如下
preOrder : 1 2 4 5 3 6 中左右
midOrder : 4 2 5 1 3 6 左中右
postOrder: 4 5 2 6 3 1 左右中;

#endif

//非递归形式,迭代循环,使用栈
void preOrderIterator(TreeNode * r) //先序
{
    if(r)
    {
        Stack s;
        initStack(&s);
        while (r || !isStackEmpty(&s)) // r 不为空即或者栈内不为空
        {
            while (r)  //若 r 不为空,则一直指向左节点,给左节点压栈,直到左节点为空
            {
                printf("%d ",r->_data);
                push(&s,r);
                r=r->_left;
                //压栈
            }
            r=pop(&s);  //左节点为空,则弹出,判断是否存在右节点,若有则继续判断左节点
            r=r->_right;
            //出栈
        }
    }
}

void midOrderIterator(TreeNode * r) //中序
{
    if(r)
    {
        Stack s;
        initStack(&s);
        while (r || !isStackEmpty(&s))
        {
            while (r)
            {
                push(&s,r);
                r=r->_left;
                //压栈
            }
            r=pop(&s);
            printf("%d ",r->_data);  //实际就是改变打印输出顺序
            r=r->_right;
            //出栈
        }
    }
}

void postdOrderIterator(TreeNode * r) //后序,逻辑较复杂
{
    if(r)
    {
        Stack s;
        initStack(&s);
        TreeNode *cur; //当前结点
        TreeNode *pre=NULL; //前一次访问的结点
        push(&s,r);
        while(!isStackEmpty(&s))
        {
            cur = pop(&s);    
            push(&s,cur);  //这一步实际上就是在拿取栈顶的节点,来判断此节点的左右是否有子节点。
            if((cur->_left==NULL&&cur->_right==NULL)||
               (pre!=NULL&&(pre==cur->_left||pre==cur->_right)))
            {
                //如果当前结点没有子结点或者子节点都已被访问过
                printf("%d ",cur->_data);
                pop(&s);
                pre=cur;
            }
            else
            {
                if(cur->_right != NULL)
                    push(&s,cur->_right);
                if(cur->_left != NULL)
                    push(&s,cur->_left);
            }
        }
    }
}
int main()
{
    TreeNode a,b,c,d,e,f;    //画树
    TreeNode * root = &a;
    a._data=1;b._data=2;c._data=3;
    d._data=4;e._data=5;f._data=6;
    a._left=&b;a._right=&c;
    b._left=&d;b._right=&e;
    c._left=NULL; c._right=&f;
    d._left=d._right=e._left=e._right=f._left=f._right=NULL;


    preOrderIterator(root);
    putchar(10);
    midOrderIterator(root);
    putchar(10);
    postdOrderIterator(root);
    return 0;
}

3.补充:求树高度的函数

int getHeightByPostOrder(TreeNode  * t)
{
    int lH, rH, maxH;
    if(t)
    {
        lH = getHeightByPostOrder(t->_left); //求左右高度,然后取出最大的
        rH = getHeightByPostOrder(t->_right);
        maxH = (lH>rH)?lH:rH;
        return maxH +1;
    }
    else
        return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

树(Tree)——(二)链式存储 的相关文章

  • 带头双向循环链表:一种高效的数据结构

    博客主页 江池俊的博客 收录专栏 数据结构探索 专栏推荐 cpolar C语言进阶之路 代码仓库 江池俊的代码仓库 编译环境 Visual Studio 2022 欢迎大家点赞 评论 收藏 文章目录 一 带头循环双向链表的概念及结构 二 使
  • 算法与数据结构(二十五)TopK问题:基于快排的Python模板

    首先 先写partition模板 def partition nums left right pivot nums left 初始化一个待比较数据 i j left right while i lt j while i
  • LeetCode:1038. 从二叉搜索树到更大和树(反向中序遍历 C++、Java)

    目录 1038 从二叉搜索树到更大和树 题目描述 实现代码与解析 dfs 原理思路 1038 从二叉搜索树到更大和树 题目描述 给定一个二叉搜索树 root BST 请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和 提醒一
  • 算法题-简单系列-06-删除有序链表中重复的元素

    文章目录 1 题目 1 1 循环遍历 1 题目 1 1 循环遍历 既然连续相同的元素只留下一个 我们留下哪一个最好呢 当然是遇到的第一个元素了 因为第一个元素直接就与前面的链表节点连接好了 前面就不用管了 只需要跳过后面重复的元素 连接第一
  • 算法设计与实现--贪心篇

    贪心算法 贪心算法是一种在每一步选择中都采取当前状态下最优决策的算法 以期望能够通过一系列局部最优的选择达到全局最优 贪心算法的关键是定义好局部最优的选择 并且不回退 即一旦做出了选择 就不能撤销 一般来说 贪心算法适用于满足以下两个条件的
  • 不会做的题汇总

    摘苹果 题目描述 小红来到苹果园 帮园长摘苹果 园长请小红把摘完的苹果的最小的那个去掉 如果有 多个最小的苹果 那么都要去掉 剩余的苹果算一下平均一个苹果有多重 平均重 量请保留1位小数 输入 输入有2行 第一行 一个整数n代表小红摘的n个
  • c 关于数组几个查序程序

    1 查询某元素是否在数组中 int main void char i 10 2 1 7 2 10 5 2 0 1 4 10 10 1 3 1 0 8 char z 10 1 2 3 4 1 4 6 8 0 9 int zz 0 标志位 0
  • 每日一练2023.12.17——大笨钟的心情【PTA】

    题目链接 L1 077 大笨钟的心情 题目要求 有网友问 未来还会有更多大笨钟题吗 笨钟回复说 看心情 本题就请你替大笨钟写一个程序 根据心情自动输出回答 输入格式 输入在一行中给出 24 个 0 100 区间内的整数 依次代表大笨钟在一天
  • 力扣每日一题:162. 寻找峰值(2023-12-18)

    力扣每日一题 题目 162 寻找峰值 日期 2023 12 18 用时 10 m 9 s 时间 0 ms 内存 40 54 MB 代码 class Solution public int findPeakElement int nums i
  • 代码随想录算法训练营第42天| ● 01背包问题,你该了解这些! ● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集

    416 分割等和子集 已解答 中等 相关标签 相关企业 给你一个 只包含正整数 的 非空 数组 nums 请你判断是否可以将这个数组分割成两个子集 使得两个子集的元素和相等 示例 1 输入 nums 1 5 11 5 输出 true 解释
  • 回溯算法第零篇【递归、搜索与回溯】【回溯算法入门必看】

    本篇文章的目的 1 给小伙伴们对回溯算法中的名词进行解释 2 消除递归的恐惧 回溯是递归的一个分支 给小伙伴们一个建议 整篇文章都要看完 一字不漏 全是干货 注意 分析回溯的思想之前 我们得知道一个关系 递归包含搜索 搜索包含回溯 所以我们
  • Leetcode 55 跳跃游戏

    题意理解 非负整数数组 nums 最初位于数组的 第一个下标 数组中的每个元素代表你在该位置可以跳跃的最大长度 需要跳到nums最后一个元素即为成功 目标 是否能够跳到最后一个元素 解题思路 使用贪心算法来解题 需要理解局部解和最优解的关系
  • LeetCode 2397. 被列覆盖的最多行数,状态压缩优化回溯法

    一 题目 1 题目描述 给你一个下标从 0 开始 大小为 m x n 的二进制矩阵 matrix 另给你一个整数 numSelect 表示你必须从 matrix 中选择的 不同 列的数量 如果一行中所有的 1 都被你选中的列所覆盖 则认为这
  • 浅谈归并排序:合并 K 个升序链表的归并解法

    在面试中遇到了这道题 如何实现多个升序链表的合并 这是 LeetCode 上的一道原题 题目具体如下 用归并实现合并 K 个升序链表 LeetCode 23 合并K个升序链表 给你一个链表数组 每个链表都已经按升序排列 请你将所有链表合并到
  • 搜索二叉树(BSTree)

    一 搜索二叉树的概念 二叉搜索树又称为做二叉排序树 二叉查找树 其要么是一棵空树 要么是一个满足以下性质的二叉树 若它的左子树不空 则左子树上所有结点的关键字均小于根结点关键字 若它的右子树不空 则右子树上所有结点的关键字均大于根结点关键字
  • 206.翻转链表

    翻转链表 力扣 LeetCode 官网 全球极客挚爱的技术成长平台 备战技术面试 力扣提供海量技术面试资源 帮助你高效提升编程技能 轻松拿下世界 IT 名企 Dream Offer https leetcode cn problems re
  • 「优选算法刷题」:移动零

    嗨 这个假期罗根开始接触了算法 在为今年的蓝桥杯做准备 所以 开个新专栏 记录记录自己做算法题时的心得 一 题目 给定一个数组 nums 编写一个函数将所有 0 移动到数组的末尾 同时保持非零元素的相对顺序 请注意 必须在不复制数组的情况下
  • 「优选算法刷题」:快乐数

    一 题目 编写一个算法来判断一个数 n 是不是快乐数 快乐数 定义为 对于一个正整数 每一次将该数替换为它每个位置上的数字的平方和 然后重复这个过程直到这个数变为 1 也可能是 无限循环 但始终变不到 1 如果这个过程 结果为 1 那么这个
  • 用栈实现队列(OJ中报错的处理)

    用栈实现队列 ERROR AddressSanitizer myQueueFree函数中栈的释放处现了问题 没有调用StackDestory而是直接free了 这个是栈初始化时 capacity与malloc申请的空间大小没有匹配 请你仅使
  • 最大流-Dinic算法,原理详解,四大优化,详细代码

    文章目录 零 前言 一 概念回顾 可略过 1 1流网络 1 2流 1 3最大流 1 4残留网络 1 5增广路

随机推荐

  • 记一次浏览器下载错误处理-失败网络错误

    背景 最近在自己电脑上Chrome浏览器正常使用 但只要是下载软件 就会在下载几十秒后 自动停止 报失败 网络错误 导致文件都下载不成功 如下图 猜测是更改了哪块的配置 导致一直中断 可以依次检查以下几种方案 1 检查下载文件目录是否存在
  • 双十一一大波建站优惠来袭,这不薅点来建站?

    双十一 哟呼 一年一度双十一又到了 看了一下今年双十一 确实是今年以来 最优惠的时候 这次就教大家买配套服务来建站吧 先说一下个人用户 再说一下企业用户 注意 个人用户可以薅的 企业用户也可以先去薅了先 本文只做优惠购买引导嗷 需要具体建站
  • C++ —— Argument Dependent Lookup

    命名空间的出现对于C 的影响是非常大的 比如说using声明和using指令或者使用namespace作用域加以限定的名字 还记得自己阅读的第一份源码是Laurent Gomila写的SFML游戏引擎 的源代码 阅读的第一份源码居然如此优美
  • 【03.02】大数据的多任务编程-进程

    当涉及到大数据处理时 多任务编程和进程管理是非常重要的概念 Python 提供了一些强大的库来处理这些任务 其中最常用的是 multiprocessing 模块 在本教程中 我们将使用 multiprocessing 模块来展示一个有关大数
  • RockerMQ集群部署

    目录 一 Broker集群模式 1 单Master 2 多Master多Slave模式异步复制 3 多Master多Slave模式同步双写 二 集群搭建实践 1 集群架构 2 克隆生成rocketmqos1 3 修改rocketmqos1配
  • Ubuntu-使用Xftp和Xshell连接

    流程如下 1 检查是否安装了 vsftpd vsftpd version 如果没有安装 则使用如下命令进行安装 apt get install vsftpd 2 检测是否安装了ssh ps e grep ssh 如果没有安装 则使用如下命令
  • 华为云备份会上传私密相册吗_2 亿部华为手机背后,这个功能不能忽视

    原标题 2 亿部华为手机背后 这个功能不能忽视 华为消费者业务昨天宣布 在全球消费者和合作伙伴的热情支持下 凭借华为 P20 系列 Mate20 系列 荣耀10 等多款华为 荣耀机型在市场上的优异表现 2018 年华为智能手机发货量 含荣耀
  • 逆序输出 之(单词整体顺序不变,单词的每个字母逆序输出)

    字符串反转 题目描述 小C很喜欢倒着写单词 现在给你一行小C写的文本 你能把每个单词都反转并输出它们吗 输入 输入包含多组测试样例 第一行为一个整数T 代表测试样例的数量 后面跟着T个测试样例 每个测试样例占一行 包含多个单词 一行最多有1
  • 【Java基础】重写equals方法详讲

    一 重写equals方法 Java比较学习 重写equals方法的安全写法 1 重写equals方法的两种方式 这里提供两个比较常见的equals重写方法 用instanceof实现重写equals方法 用getClass实现重写equal
  • 【Mojo】[英] Getting Started with Mojo ️‍

    本文共计5171字 预计阅读时间5分钟 注 此文被列入翻译计划 Mojo the new Programming Language for all AI developers is as simple as Python and as fa
  • wincc使用C脚本实现用户登录

    C脚本实现用户登录 脚本介绍 案例介绍 程序案例 脚本介绍 登录 pragma code useadmin dll include PWRT api h pragma code PWRTLogin 1 PWRTLogin 参数必须是 CHA
  • 如何用 Python 获取实时的股票数据?

    这个我会 先上图 这篇回答中 我将向你展示两种不同的代码版本 加强版和一般版 代码运行环境说明 非常重要 Python版本要求 Python 3 需要安装的库 efinance 库的安装方法是 打开 cmd 命令提示符或者其他终端工具 输入
  • moshi 极简封装

    目录 前言 Jackson的基本使用 Jackson获取泛型类型的巧妙处理 借鉴jackson优化moshi的封装 使用 总结 前言 之前写了一篇文章是介绍moshi的基本使用和实战 感兴趣的可以先看一下对kotlin友好的现代 JSON
  • Linux命令:kill

    kill命令 终止某个指定PID的服务进程 root LAPTOP HJMUH10E home simon kill 97 killall命令 终止某个指定名称的服务所对应的全部进程 root LAPTOP HJMUH10E home si
  • ESP32S3学习——SPIFFS 文件系统

    芯片 esp32s3 开发环境 espidfv4 4 一 官网相关资料 1 简介 SPIFFS 是一个用于 SPI NOR flash 设备的嵌入式文件系统 支持磨损均衡 文件系统一致性检查等功能 2 说明 目前 SPIFFS 尚不支持目录
  • Unity3D课程——离散仿真基础

    解释游戏对象 GameObjects 和 资源 Assets 的区别与联系 区别 GameObject 是由unity创建的实例 在场景中所有实际使用的对象都是游戏对象 即出现在场景栏中的对象 Asset 是可以用于游戏中的具体资源 如脚本
  • 数字IC验证:ARM总线协议AMBA中AHB、APB的简介、区别与联系

    写在前面 最近实习项目里用到这2个协议 因此简单整理一下 内容大多来自ARM官方文档与网络上的 我主要做一个整合 加上自己的理解补充 内容来源都会分别标出 如有侵权请指出 立刻删帖 官方文档入口 AMBA 包括AHB ASB APB 文章目
  • RocketMQ-名词和架构

    RocketMQ rocketMQ是做什么的我就不用解释了吧 以及他的背景 本文主要是为了让大家明白RocketMQ的工作原理 架构图 上图 双箭头代表是双向通信 ProducerGroup和ConsumerGroup以及Broker集群
  • 常说的一区二区含义是什么?

    一区和二区是对于SCI期刊的划分 用于评估期刊的学术声誉和影响力 这种划分通常是指SCI期刊的影响因子 Impact Factor 范围 一区期刊 Q1 是指影响因子排名靠前的期刊 即影响因子在某个学科领域中排名前25 的期刊 一区期刊通常
  • 树(Tree)——(二)链式存储

    用代码实现前序 中序 后序 第一种方法就是使用递归 另一种是使用栈 将分别讲述 目录 1 递归实现 main函数 C语言版本 2 利用栈实现 mystack h mystack cpp main函数 3 补充 求树高度的函数 1 递归实现