当前位置: 首页 > article >正文

二叉树和表达式树的实现

二叉树的介绍二叉树是树这种数据结果的一种特殊情况其每个节点的子节点树不能超过两个二叉树差不多就是树中最常用的特殊结构了。二叉树的分类满二叉树国外定义由度为0和2的结点构成的树没有度为1的节点。国内定义每一层都是满结点高度为k的二叉树的结点固定为。完全二叉树按层序从上到下从左到右编号空缺只能出现在最后一层的最右侧前面所有层必须满。完美二叉树国外定义每一层都是满结点高度为k的二叉树的结点固定为。国内定义每一层都是满结点高度为k的二叉树的结点固定为。扩充二叉树在原二叉树所有空子树的位置添加上空结点。二叉树的性质①二叉树的第k层最多有个节点。②深度为d的二叉树最多有个节点③设一棵树中度为i的节点数为则总节点数N可以推出解释主要是解释N由于一个度为2的结点会挂两个结点一个度为1的结点会挂1个节点一个度为0的叶子节点不挂节点所以按道理就是树的总结点数但是根节点没有其它节点挂着它所以上述式子没有算上根节点如果算上根节点的话就加1就行了。二叉树的实现二叉树的数据结构typedef int ElementType; struct TreeNode; typedef struct TreeNode *PtrToNode; typedef PtrToNode Tree; struct TreeNode { ElementType Element; Tree Left; Tree Right; }; Tree CreateTree(ElementType rootElement); PtrToNode CreateNode(ElementType element); void InsertLeftChild(PtrToNode parent, ElementType element); void InsertRightChild(PtrToNode parent, ElementType element); void PreOrderTraversal(Tree T); void InOrderTraversal(Tree T); void PostOrderTraversal(Tree T); void DestroyTree(Tree T);这里依然把二叉树的所有节点都看成是一个个指向struct TreeNode对象的指向每个节点包含存储的数据以及这个节点指向其左右两个子节点的指针。树和节点的创建及销毁Tree CreateTree(ElementType rootElement) { Tree T (Tree)malloc(sizeof(struct TreeNode)); if (T NULL) { printf(Failed to allocate memory for the new Tree\n); return NULL; } T-Element rootElement; T-Left NULL; T-Right NULL; return T; } PtrToNode CreateNode(ElementType element) { PtrToNode node (PtrToNode)malloc(sizeof(struct TreeNode)); if (node NULL) { printf(Failed to allocate memory for the new Tree\n); return NULL; } node-Element element; node-Left NULL; node-Right NULL; return node; } void DestroyTree(Tree T) { if (T ! NULL) { DestroyTree(T-Left); DestroyTree(T-Right); free(T); } }创建一个二叉树对象其实就是创建一个根节点如果想要实现节点与节点之间的联系就需要用到左右子节点插入的函数。左右子节点的插入void InsertLeftChild(PtrToNode parent,ElementType element) { if (parent NULL) { printf(Parent is NULL\n); return; } if (parent-Left ! NULL) { printf(The LeftChild already exists); return; } parent-Left CreateNode(element); } void InsertRightChild(PtrToNode parent,ElementType element) { if (parent NULL) { printf(Parent is NULL\n); return; } if (parent-Right ! NULL) { printf(The RightChild already exists); } parent-Right CreateNode(element); }对于左子节点插入的函数其逻辑就是先创建一个数据为element的节点然后让parent这个父节点的Left指针指向这个节点。右子节点的插入也是同理。前中后序遍历void PreOrderTraversal(Tree T) { if (T ! NULL) { printf(%d, T-Element); PreOrderTraversal(T-Left); PreOrderTraversal(T-Right); } } void InOrderTraversal(Tree T) { if (T ! NULL) { InOrderTraversal(T-Left); printf(%d, T-Element); InOrderTraversal(T-Right); } } void PostOrderTraversal(Tree T) { if (T ! NULL) { PostOrderTraversal(T-Left); PostOrderTraversal(T-Right); printf(%d, T-Element); } }得益于树的结构其前中后序的遍历只需要简单的递归就能实现以前序遍历(根左右)为例先打印输出根节点的值然后再遍历根节点的左边左边也是一棵树这样根节点的左子节点就相当于这棵树的头节点根据根左右的顺序就遍历这个头节点然后再以它的左节点开始把它的左节点看成头节点周而复始地进行根左右这个顺序的遍历。其他情况同理。实例int main() { Tree T CreateTree(1); InsertLeftChild(T, 2); InsertRightChild(T, 3); InsertLeftChild(T-Left, 4); InsertRightChild(T-Left, 5); PreOrderTraversal(T); printf(\n); InOrderTraversal(T); printf(\n); PostOrderTraversal(T); DestroyTree(T); return 0; }结果如下表达式树的介绍表达式树指的是其树上的节点存储的都是表达式的元素由于加减乘除这样的运算都是对两个值进行的运算而二叉树的每个节点的子节点又可以恰好为两个所有理所应当地就可以用二叉树来存储一个由加减乘除构成的表达式了。以下算法可以实现后缀表达式的输入而进行中缀表达式及其式子运算后的值的输出。程序由豆包生成。表达式树的实现表达式树的结构typedef union { char op; // 操作符 int num; // 操作数这里用整数举例 } ElementType; struct TreeNode; typedef struct TreeNode *PtrToNode; typedef PtrToNode Tree; struct TreeNode { ElementType data; int isOperator; // 标记是操作符(1)还是操作数(0) Tree Left; Tree Right; };树的节点有四个变量首先是存储的值这个值可以是一个数字也可以是一个运算符所有其数据类型为union其次还需要一个用于标记这个节点存储的是数字还有运算符的记号最后就是指向左右节点的指针。栈的辅助结构// 栈的辅助结构用于存储树的指针 typedef struct StackNode { Tree tree; struct StackNode *next; } StackNode, *Stack; // 创建空栈 Stack CreateStack() { Stack s (Stack)malloc(sizeof(StackNode)); s-next NULL; return s; } // 判断栈空 int IsStackEmpty(Stack s) { return s-next NULL; } // 压栈 void Push(Stack s, Tree t) { StackNode *newNode (StackNode *)malloc(sizeof(StackNode)); newNode-tree t; newNode-next s-next; s-next newNode; } // 弹栈 Tree Pop(Stack s) { if (IsStackEmpty(s)) { printf(栈空无法弹栈\n); exit(1); } StackNode *top s-next; Tree t top-tree; s-next top-next; free(top); return t; }由于算法涉及到需要把一个后缀表达式拆解再将每个部分放到二叉树中所以这里用栈这种数据结构来方便以上步骤的进行。后缀表达式转表达式树// 创建操作数节点 Tree CreateNumNode(int num) { Tree t (Tree)malloc(sizeof(struct TreeNode)); t-data.num num; t-isOperator 0; t-Left NULL; t-Right NULL; return t; } // 创建操作符节点 Tree CreateOpNode(char op, Tree left, Tree right) { Tree t (Tree)malloc(sizeof(struct TreeNode)); t-data.op op; t-isOperator 1; t-Left left; t-Right right; return t; } // 后缀表达式转表达式树 Tree BuildExpressionTree(char *postfix) { Stack s CreateStack(); int len strlen(postfix); for (int i 0; i len; i) { char c postfix[i]; if (c ) continue; // 跳过空格 if (c 0 c 9) { // 处理多位数简单处理假设是单个数字 int num c - 0; Tree numTree CreateNumNode(num); Push(s, numTree); } else if (c || c - || c * || c /) { // 操作符弹出右子树、左子树 Tree right Pop(s); Tree left Pop(s); Tree opTree CreateOpNode(c, left, right); Push(s, opTree); } } Tree exprTree Pop(s); free(s); // 释放栈 return exprTree; }需要说明的是为了简便这个算法不能识别多位数字。首先开始对后缀表达式遍历如果遍历到的是数字那就存入栈中如果遍历到操作符先把这个操作符封装成一个节点然后从栈中弹出两个节点让这个操作符节点的左右子节点分别为这两个节点最后再将这个操作符节点压栈以便之后成为别的操作符节点的子节点。最后整个栈只会有一个节点这个节点其实就是最终的表达式树把它弹出来后栈就是空栈了此时就可以释放栈的空间了。中缀表达式的输出// 中序遍历输出中缀表达式自动加括号 void InOrderExpr(Tree t) { if (t NULL) return; if (t-isOperator) printf((); InOrderExpr(t-Left); if (t-isOperator) { printf(%c, t-data.op); } else { printf(%d, t-data.num); } InOrderExpr(t-Right); if (t-isOperator) printf()); }当得到表达式二叉树后对它进行后序遍历得到的就是后序表达式对它进行中序遍历得到的就是中序表达式。表达式树的求值// 表达式树求值 int EvaluateExprTree(Tree t) { if (t NULL) return 0; if (!t-isOperator) { return t-data.num; // 操作数直接返回 } int leftVal EvaluateExprTree(t-Left); int rightVal EvaluateExprTree(t-Right); switch (t-data.op) { case : return leftVal rightVal; case -: return leftVal - rightVal; case *: return leftVal * rightVal; case /: return leftVal / rightVal; default: printf(未知操作符\n); exit(1); } }这里通过后序遍历得到表达式树的值。其表达式树长这样实例int main() { // 后缀表达式3 4 5 * → 对应中缀 (34)*5 char postfix[] 3 4 5 *; Tree exprTree BuildExpressionTree(postfix); printf(中缀表达式); InOrderExpr(exprTree); printf(\n); int result EvaluateExprTree(exprTree); printf(表达式结果%d\n, result); // 可选销毁树 // DestroyTree(exprTree); return 0; }结果如下

相关文章:

二叉树和表达式树的实现

二叉树的介绍二叉树是树这种数据结果的一种特殊情况,其每个节点的子节点树不能超过两个,二叉树差不多就是树中最常用的特殊结构了。二叉树的分类满二叉树国外定义:由度为0和2的结点构成的树,没有度为1的节点。国内定义&#xff1a…...

Python DXF自动化处理:解决CAD图纸批量操作的5大痛点

Python DXF自动化处理:解决CAD图纸批量操作的5大痛点 【免费下载链接】ezdxf Python interface to DXF 项目地址: https://gitcode.com/gh_mirrors/ez/ezdxf ezdxf是Python生态中功能最全面的DXF文件处理库,为开发者提供了从R12到R2018全版本DXF文…...

从TB67H450FNG这颗驱动芯片入手,手把手教你理解电机控制里的PWM、FOC和PID到底在干啥

从TB67H450FNG芯片实战解析电机控制三大核心技术 当我们第一次拆开一台3D打印机或机械臂的驱动模块时,那些密密麻麻的芯片和术语总让人望而生畏。作为电机驱动领域的经典芯片,东芝的TB67H450FNG就像一位耐心的向导,通过它简洁的引脚和明确的…...

LeetCode 123. Best Time to Buy and Sell Stock III 题解

LeetCode 123. Best Time to Buy and Sell Stock III 题解 题目描述 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意: 你不能同时参与多笔交易(你…...

吊打大模型幻觉!保姆级RAG原理+极简实战代码,新手一秒看懂

吊打大模型幻觉!保姆级RAG原理极简实战代码,新手一秒看懂 前言:拒绝晦涩干货,通俗讲透RAG 很多小伙伴初学大模型的时候,都会遇到一个让人崩溃的问题:AI瞎编乱造! 问它最新技术,它一问…...

音乐标签管理革命:告别混乱,拥抱智能音乐库

音乐标签管理革命:告别混乱,拥抱智能音乐库 【免费下载链接】music-tag-web 音乐标签编辑器,可编辑本地音乐文件的元数据(Editable local music file metadata.) 项目地址: https://gitcode.com/gh_mirrors/mu/music…...

智读致用|《一人企业》4|扩张不是战略,活下来才是

系列:《一人企业》读书笔记 第4章 书名:《一人企业:一个人也能赚钱的商业新模式》 作者:保罗贾维斯(Paul Jarvis) 所有人都在教你怎么做大。 融资、招人、开分公司、冲GMV——这套叙事太熟悉了&#xff0c…...

RSA参数生成实战秘籍:rsatool带你掌握密码学核心技能

RSA参数生成实战秘籍:rsatool带你掌握密码学核心技能 【免费下载链接】rsatool rsatool can be used to calculate RSA and RSA-CRT parameters 项目地址: https://gitcode.com/gh_mirrors/rs/rsatool 在密码学领域,RSA算法无疑是现代安全通信的基…...

Cursor AI编辑器使用体验优化方案:智能配置管理与功能扩展技术解析

Cursor AI编辑器使用体验优化方案:智能配置管理与功能扩展技术解析 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reac…...

原神帧率解锁终极指南:如何轻松突破60FPS限制享受流畅游戏体验

原神帧率解锁终极指南:如何轻松突破60FPS限制享受流畅游戏体验 【免费下载链接】genshin-fps-unlock unlocks the 60 fps cap 项目地址: https://gitcode.com/gh_mirrors/ge/genshin-fps-unlock 你是否厌倦了《原神》PC版60FPS的限制?当你的高刷新…...

Divinity Mod Manager:彻底解决《神界:原罪2》模组管理难题的完整方案

Divinity Mod Manager:彻底解决《神界:原罪2》模组管理难题的完整方案 【免费下载链接】DivinityModManager A mod manager for Divinity: Original Sin - Definitive Edition. 项目地址: https://gitcode.com/gh_mirrors/di/DivinityModManager …...

WeDLM-7B-Base GPU部署:NVIDIA Triton推理服务器封装与批量请求优化

WeDLM-7B-Base GPU部署:NVIDIA Triton推理服务器封装与批量请求优化 1. 模型概述与核心优势 WeDLM-7B-Base是一款基于扩散机制(Diffusion)的高性能基座语言模型,拥有70亿参数规模。该模型在标准因果注意力机制下实现了并行掩码恢…...

如何快速掌握音频频谱分析:Spek声学工具终极指南

如何快速掌握音频频谱分析:Spek声学工具终极指南 【免费下载链接】spek Acoustic spectrum analyser 项目地址: https://gitcode.com/gh_mirrors/sp/spek 你是否曾经好奇音乐中的高低频分布?或者想检查录音中的噪声问题?Spek就是你的答…...

D3KeyHelper:如何用智能按键管理解决暗黑3的五大操作难题

D3KeyHelper:如何用智能按键管理解决暗黑3的五大操作难题 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面,可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 在暗黑破坏神3的高强度游戏体验…...

FLUX.1-Krea-Extracted-LoRA快速上手:bash /root/start.sh启动原理与日志查看方法

FLUX.1-Krea-Extracted-LoRA快速上手:bash /root/start.sh启动原理与日志查看方法 1. 模型概述 FLUX.1-Krea-Extracted-LoRA 是一款基于 FLUX.1-dev 基础模型的真实感图像生成模型,通过提取的 LoRA 风格权重为图像注入专业摄影级别的真实感美学。该模型…...

单片机软件架构实战:从新手到高手的9种设计模式

1. 单片机软件架构入门&#xff1a;从main函数到模块化设计 刚接触单片机编程时&#xff0c;我们往往从一个简单的main函数开始。记得我第一次用51单片机点亮LED时&#xff0c;代码简单到只有十几行&#xff1a; #include <reg51.h> void main() {while(1) {P1 0x00; …...

基于Harness Engineering的零代码AI智能体开发平台Nexent深度解析

1. 项目概述&#xff1a;当“零代码”遇上“工程化”&#xff0c;AI智能体开发的新范式 最近在AI应用开发圈子里&#xff0c;一个词被反复提及&#xff1a; Agentic AI &#xff0c;或者说智能体。大家可能都体验过ChatGPT这类对话模型&#xff0c;它们能回答问题、写写代码&…...

AI智能体如何自主操作GitHub仓库:从代码理解到自动化PR全流程解析

1. 项目概述&#xff1a;当GitHub仓库成为你的AI智能体最近在AI应用开发圈里&#xff0c;一个名为open-gitagent/gitagent的项目开始被频繁提及。乍一看&#xff0c;它像是一个普通的GitHub仓库&#xff0c;但当你深入其中&#xff0c;会发现它试图解决一个非常具体且前沿的问题…...

基于Cognita框架构建企业级RAG知识库:从原理到生产部署全解析

1. 项目概述&#xff1a;当向量数据库遇上RAG&#xff0c;Cognita如何重塑企业知识管理最近在折腾企业内部的文档智能问答系统&#xff0c;相信很多同行都踩过类似的坑&#xff1a;费劲把PDF、Word、PPT这些非结构化文档灌进向量数据库&#xff0c;然后基于RAG&#xff08;检索…...

别再用FR4不行了!实测12G-SDI在普通PCB板材上的完整布线指南(附阻抗计算与AntiPad避坑)

别再用FR4不行了&#xff01;实测12G-SDI在普通PCB板材上的完整布线指南&#xff08;附阻抗计算与AntiPad避坑&#xff09; 在高速数字视频传输领域&#xff0c;12G-SDI作为4K/60fps内容的主流接口标准&#xff0c;其PCB设计一直被视为需要特殊高频板材的"贵族技术"。…...

5步完成高效MOOC课程离线下载:MoocDownloader终极指南

5步完成高效MOOC课程离线下载&#xff1a;MoocDownloader终极指南 【免费下载链接】MoocDownloader An MOOC downloader implemented by .NET. 一枚由 .NET 实现的 MOOC 下载器. 项目地址: https://gitcode.com/gh_mirrors/mo/MoocDownloader 您是否曾因网络不稳定而无法…...

Qianfan-OCR识别结果后处理实战:正则表达式与自然语言处理技巧

Qianfan-OCR识别结果后处理实战&#xff1a;正则表达式与自然语言处理技巧 1. 引言&#xff1a;为什么需要OCR后处理 OCR技术虽然已经相当成熟&#xff0c;但在实际应用中&#xff0c;识别结果往往存在各种问题。你可能遇到过这样的情况&#xff1a;从名片上扫描的电话号码多…...

AltSnap:Windows窗口管理革命,5分钟掌握高效桌面操作

AltSnap&#xff1a;Windows窗口管理革命&#xff0c;5分钟掌握高效桌面操作 【免费下载链接】AltSnap Maintained continuation of Stefan Sundins AltDrag 项目地址: https://gitcode.com/gh_mirrors/al/AltSnap 你是否曾在Windows中为精确点击窗口标题栏而烦恼&#…...

CSS 属性选择器

CSS 属性选择器 CSS 属性选择器是一种用于选择具有特定属性值的元素的选择器。通过属性选择器,开发者可以更加精确地控制页面中特定元素的外观和行为。本文将详细介绍 CSS 属性选择器的概念、使用方法和示例。 一、属性选择器的概念 属性选择器允许开发者根据元素所具有的属…...

Fairseq-Dense-13B-Janeway部署教程:开源可部署+GPU算力适配+镜像免配置三大优势实证

Fairseq-Dense-13B-Janeway部署教程&#xff1a;开源可部署GPU算力适配镜像免配置三大优势实证 1. 模型概述 Fairseq-Dense-13B-Janeway 是 KoboldAI 发布的 130 亿参数创意写作大模型&#xff0c;专门针对科幻与奇幻题材进行优化。该模型使用 2210 本科幻与奇幻题材电子书进…...

OpenModScan:工业自动化工程师必备的免费Modbus调试工具终极指南

OpenModScan&#xff1a;工业自动化工程师必备的免费Modbus调试工具终极指南 【免费下载链接】OpenModScan Open ModScan is a Free Modbus Master (Client) Utility 项目地址: https://gitcode.com/gh_mirrors/op/OpenModScan OpenModScan是一款功能强大的免费开源Modb…...

LFM2.5-1.2B-Instruct行业落地:跨境电商多语言商品描述自动生成

LFM2.5-1.2B-Instruct行业落地&#xff1a;跨境电商多语言商品描述自动生成 1. 模型介绍与部署准备 LFM2.5-1.2B-Instruct是一个1.2B参数量的轻量级指令微调大语言模型&#xff0c;特别适合在边缘设备或低资源服务器上运行。该模型支持8种主流语言&#xff0c;包括英语、中文…...

从数据标注到模型部署:基于YOLOv8+RT-DETR的车道抛洒物检测保姆级全流程(含labelImg使用教程)

车道抛洒物检测实战&#xff1a;从零构建YOLOv8与RT-DETR融合模型 项目背景与核心价值 高速公路和城市道路上突然出现的抛洒物&#xff08;如碎石、货物残渣、轮胎碎片&#xff09;是引发交通事故的重要隐患。传统人工巡检方式效率低下且成本高昂&#xff0c;而基于深度学习的实…...

Element UI项目里藏了个老版本lodash?手把手教你排查和修复这个原型污染漏洞

Element UI项目中隐藏的lodash漏洞&#xff1a;从定位到修复的完整指南 引言 最近一次例行安全扫描后&#xff0c;我的团队收到了一个令人不安的警报&#xff1a;我们的Vue项目存在lodash原型污染漏洞。奇怪的是&#xff0c;项目package.json中根本没有直接声明lodash依赖。经过…...

Nano-Banana Studio惊艳效果:复古画报风Sportswear suit爆炸图生成实录

Nano-Banana Studio惊艳效果&#xff1a;复古画报风Sportswear suit爆炸图生成实录 1. 引言&#xff1a;当AI遇见复古时尚设计 想象一下这样的场景&#xff1a;你正在为一款运动套装设计宣传材料&#xff0c;想要展示服装的每一个细节——从缝线工艺到面料纹理&#xff0c;从…...