数据结构(19):二叉树的三叉链表表示
程序代码//二叉树的三叉链表存储#includestdio.h#includestdlib.h#definemax(a, b) a b ? a : b#defineClearBiTree DestroyBiTreetypedefcharTElemType;// 二叉树的三叉链表存储表示typedefstructBiTPNode{TElemType data;structBiTPNode*parent,*lchild,*rchild;// 双亲、左右孩子指针}BiTPNode,*BiPTree;typedefBiPTree QElemType;// 设队列元素为二叉树的指针类型typedefstructQNode{QElemType data;//数据域structQNode*next;//指针域}QNode,*QueuePtr;typedefstruct{QueuePtr front,//队头指针指针域指向队头元素rear;//队尾指针指向队尾元素}LinkQueue;TElemType Nil#;// 字符型以空格符为空// 构造空二叉树TintInitBiTree(BiPTree*T){*TNULL;return1;}// 销毁二叉树TvoidDestroyBiTree(BiPTree*T){if(*T)// 非空树{if((*T)-lchild)// 有左孩子DestroyBiTree((*T)-lchild);// 销毁左孩子子树if((*T)-rchild)// 有右孩子DestroyBiTree((*T)-rchild);// 销毁右孩子子树free(*T);// 释放根结点*TNULL;// 空指针赋0}}// 按先序次序输入二叉树中结点的值可为字符型或整型在主程中定义// 构造仅缺双亲指针的三叉链表表示的二叉树T。变量Nil表示空子树voidCreate(BiPTree*T)// CreateBiTree()调用{TElemType ch;scanf(%c,ch);if(chNil)// 空*TNULL;else{*T(BiPTree)malloc(sizeof(BiTPNode));if(!*T)exit(0);(*T)-datach;// 生成根结点Create((*T)-lchild);// 构造左子树Create((*T)-rchild);// 构造右子树}}// 构造一个空队列QintInitQueue(LinkQueue*Q){(*Q).front(*Q).rear(QueuePtr)malloc(sizeof(QNode));//动态分配一个空间if(!(*Q).front)exit(0);(*Q).front-nextNULL;//队头指针指向空无数据域这样构成了一个空队列return1;}// 若Q为空队列,则返回1,否则返回0intQueueEmpty(LinkQueue Q){if(Q.frontQ.rear)return1;elsereturn0;}// 插入元素e为Q的新的队尾元素intEnQueue(LinkQueue*Q,QElemType e){QueuePtr p(QueuePtr)malloc(sizeof(QNode));if(!p)// 存储分配失败exit(0);//生成一个以为e为数据域的队列元素p-datae;p-nextNULL;//将该新队列元素接在队尾的后面(*Q).rear-nextp;(*Q).rearp;return1;}// 若队列不空,删除Q的队头元素,用e返回其值,并返回1,否则返回0intDeQueue(LinkQueue*Q,QElemType*e){QueuePtr p;if((*Q).front(*Q).rear)return0;p(*Q).front-next;//队头元素*ep-data;(*Q).front-nextp-next;if((*Q).rearp)(*Q).rear(*Q).front;free(p);return1;}// 按先序次序输入二叉树中结点的值可为字符型或整型在主程中定义// 构造三叉链表表示的二叉树TintCreateBiTree(BiPTree*T){LinkQueue q;QElemType a;Create(T);// 构造二叉树(缺双亲指针)if(*T)// 非空树{(*T)-parentNULL;// 根结点的双亲为空InitQueue(q);// 初始化队列EnQueue(q,*T);// 根指针入队while(!QueueEmpty(q))// 队不空{DeQueue(q,a);// 出队,队列元素赋给aif(a-lchild)// 有左孩子{a-lchild-parenta;// 给左孩子的双亲指针赋值EnQueue(q,a-lchild);// 左孩子入队}if(a-rchild)// 有右孩子{a-rchild-parenta;// 给右孩子的双亲指针赋值EnQueue(q,a-rchild);// 右孩子入队}}}return1;}// 若T为空二叉树,则返回1,否则0intBiTreeEmpty(BiPTree T){if(T)return0;elsereturn1;}// 返回T的深度intBiTreeDepth(BiPTree T){inti,j;if(!T)return0;if(T-lchild)iBiTreeDepth(T-lchild);elsei0;if(T-rchild)jBiTreeDepth(T-rchild);elsej0;returnij?i1:j1;}// 返回T的根TElemTypeRoot(BiPTree T){if(T)returnT-data;elsereturnNil;}// 返回p所指结点的值TElemTypeValue(BiPTree p){returnp-data;}// 给p所指结点赋值为valuevoidAssign(BiPTree p,TElemType value){p-datavalue;}// 返回二叉树T中指向元素值为e的结点的指针BiPTreePoint(BiPTree T,TElemType e){LinkQueue q;QElemType a;if(T)// 非空树{InitQueue(q);// 初始化队列EnQueue(q,T);// 根结点入队while(!QueueEmpty(q))// 队不空{DeQueue(q,a);// 出队,队列元素赋给aif(a-datae)returna;if(a-lchild)// 有左孩子EnQueue(q,a-lchild);// 入队左孩子if(a-rchild)// 有右孩子EnQueue(q,a-rchild);// 入队右孩子}}returnNULL;}// 若e是T的非根结点,则返回它的双亲,否则返回空TElemTypeParent(BiPTree T,TElemType e){BiPTree a;if(T)// 非空树{aPoint(T,e);// a是结点e的指针if(aa!T)// T中存在结点e且e是非根结点returna-parent-data;// 返回e的双亲的值}returnNil;// 其余情况返回空}// 返回e的左孩子。若e无左孩子,则返回空TElemTypeLeftChild(BiPTree T,TElemType e){BiPTree a;if(T)// 非空树{aPoint(T,e);// a是结点e的指针if(aa-lchild)// T中存在结点e且e存在左孩子returna-lchild-data;// 返回e的左孩子的值}returnNil;// 其余情况返回空}// 返回e的右孩子。若e无右孩子,则返回空TElemTypeRightChild(BiPTree T,TElemType e){BiPTree a;if(T)// 非空树{aPoint(T,e);// a是结点e的指针if(aa-rchild)// T中存在结点e且e存在右孩子returna-rchild-data;// 返回e的右孩子的值}returnNil;// 其余情况返回空}// 返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回空TElemTypeLeftSibling(BiPTree T,TElemType e){BiPTree a;if(T)// 非空树{aPoint(T,e);// a是结点e的指针// T中存在结点e且e存在左兄弟if(aa!Ta-parent-lchilda-parent-lchild!a)returna-parent-lchild-data;// 返回e的左兄弟的值}returnNil;// 其余情况返回空}// 返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回空TElemTypeRightSibling(BiPTree T,TElemType e){BiPTree a;if(T)// 非空树{aPoint(T,e);// a是结点e的指针// T中存在结点e且e存在右兄弟if(aa!Ta-parent-rchilda-parent-rchild!a)returna-parent-rchild-data;// 返回e的右兄弟的值}returnNil;// 其余情况返回空}// 根据LR为0或1,插入c为T中p所指结点的左或右子树。p所指结点// 的原有左或右子树则成为c的右子树。intInsertChild(BiPTree p,intLR,BiPTree c){if(p)// p不空{if(LR0){c-rchildp-lchild;if(c-rchild)// c有右孩子(p原有左孩子)c-rchild-parentc;p-lchildc;c-parentp;}else// LR1{c-rchildp-rchild;if(c-rchild)// c有右孩子(p原有右孩子)c-rchild-parentc;p-rchildc;c-parentp;}return1;}return0;// p空}// 根据LR为0或1,删除T中p所指结点的左或右子树intDeleteChild(BiPTree p,intLR){if(p)// p不空{if(LR0)// 删除左子树ClearBiTree(p-lchild);else// 删除右子树ClearBiTree(p-rchild);return1;}return0;// p空}// 先序递归遍历二叉树TvoidPreOrderTraverse(BiPTree T,int(*Visit)(BiPTree)){if(T){Visit(T);// 先访问根结点PreOrderTraverse(T-lchild,Visit);// 再先序遍历左子树PreOrderTraverse(T-rchild,Visit);// 最后先序遍历右子树}}// 中序递归遍历二叉树TvoidInOrderTraverse(BiPTree T,int(*Visit)(BiPTree)){if(T){InOrderTraverse(T-lchild,Visit);// 中序遍历左子树Visit(T);// 再访问根结点InOrderTraverse(T-rchild,Visit);// 最后中序遍历右子树}}// 后序递归遍历二叉树TvoidPostOrderTraverse(BiPTree T,int(*Visit)(BiPTree)){if(T){PostOrderTraverse(T-lchild,Visit);// 后序遍历左子树PostOrderTraverse(T-rchild,Visit);// 后序遍历右子树Visit(T);// 最后访问根结点}}// 层序遍历二叉树T(利用队列)voidLevelOrderTraverse(BiPTree T,int(*Visit)(BiPTree)){LinkQueue q;QElemType a;if(T){InitQueue(q);EnQueue(q,T);while(!QueueEmpty(q)){DeQueue(q,a);Visit(a);if(a-lchild!NULL)EnQueue(q,a-lchild);if(a-rchild!NULL)EnQueue(q,a-rchild);}}}intvisitT(BiPTree T){if(T)// T非空printf(%c是,T-data);if(T-parent)// T有双亲{printf(%c,T-parent-data);if(T-parent-lchildT)printf(的左孩子\n);elseprintf(的右孩子\n);}elseprintf(根结点\n);return1;}intmain(){inti;BiPTree T,c,q;TElemType e1,e2;InitBiTree(T);printf(构造空二叉树空否%d(1:是 0:否) 树的深度 %d\n,BiTreeEmpty(T),BiTreeDepth(T));e1Root(T);if(e1!Nil)printf(二叉树的根为: %c\n,e1);elseprintf(树空无根\n);printf(请按先序输入二叉树(如:ab三个空格表示a为根结点,b为左子树的二叉树)\n);CreateBiTree(T);printf(建立二叉树后,树空否%d(1:是 0:否) 树的深度%d\n,BiTreeEmpty(T),BiTreeDepth(T));e1Root(T);if(e1!Nil)printf(二叉树的根为: %c\n,e1);elseprintf(树空无根\n);printf(中序递归遍历二叉树:\n);InOrderTraverse(T,visitT);printf(后序递归遍历二叉树:\n);PostOrderTraverse(T,visitT);printf(层序遍历二叉树:\n);LevelOrderTraverse(T,visitT);printf(请输入一个结点的值: );scanf(%*c);scanf(%c%*c,e1);cPoint(T,e1);// c为e1的指针printf(结点的值为%c\n,Value(c));printf(欲改变此结点的值请输入新值: );scanf(%c%*c,e2);Assign(c,e2);printf(层序遍历二叉树:\n);LevelOrderTraverse(T,visitT);e1Parent(T,e2);if(e1!Nil)printf(%c的双亲是%c\n,e2,e1);elseprintf(%c没有双亲\n,e2);e1LeftChild(T,e2);if(e1!Nil)printf(%c的左孩子是%c\n,e2,e1);elseprintf(%c没有左孩子\n,e2);e1RightChild(T,e2);if(e1!Nil)printf(%c的右孩子是%c\n,e2,e1);elseprintf(%c没有右孩子\n,e2);e1LeftSibling(T,e2);if(e1!Nil)printf(%c的左兄弟是%c\n,e2,e1);elseprintf(%c没有左兄弟\n,e2);e1RightSibling(T,e2);if(e1!Nil)printf(%c的右兄弟是%c\n,e2,e1);elseprintf(%c没有右兄弟\n,e2);InitBiTree(c);printf(构造一个右子树为空的二叉树c:\n);printf(请先序输入二叉树(如:ab三个#表示a为根结点,b为左子树的二叉树)\n);CreateBiTree(c);printf(先序递归遍历二叉树c:\n);PreOrderTraverse(c,visitT);printf(树c插到树T中,请输入树T中树c的双亲结点 c为左(0)或右(1)子树: );scanf(%*c%c%d,e1,i);qPoint(T,e1);InsertChild(q,i,c);printf(先序递归遍历二叉树:\n);PreOrderTraverse(T,visitT);printf(删除子树,请输入待删除子树的双亲结点 左(0)或右(1)子树: );scanf(%*c%c%d,e1,i);qPoint(T,e1);DeleteChild(q,i);printf(先序递归遍历二叉树:\n);PreOrderTraverse(T,visitT);DestroyBiTree(T);system(pause);return0;}运行结果

相关新闻

Axure中文语言包终极指南:3分钟让你的原型设计软件说中文

Axure中文语言包终极指南:3分钟让你的原型设计软件说中文

Axure中文语言包终极指南:3分钟让你的原型设计软件说中文 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 你是否在使…

2026/7/28 14:59:18阅读更多 →
CSS入门 笔记

CSS入门 笔记

CSS(Cascading Style Sheets) 中文解释:层叠样式表 CSS的三种引入方式 行内式(内联样式):在相关的标签内使用样式(style)属性内部样式表:使用 style 标签在文档头部定义内部样式表外链式&…

2026/7/28 14:59:18阅读更多 →
vLLM与SGLang:大模型推理框架的技术对比与应用指南

vLLM与SGLang:大模型推理框架的技术对比与应用指南

1. 大模型推理框架的战场格局 2023年大模型推理领域最引人注目的现象,莫过于vLLM和SGLang这两个框架的崛起。作为长期跟踪大模型工程化的从业者,我亲眼见证了vLLM如何凭借PagedAttention技术横扫推理性能榜单,也目睹了SGLang如何通过声明式编…

2026/7/28 14:57:18阅读更多 →
TI bq2425x开关充电器评估板实战:从硬件解析到软件调试全攻略

TI bq2425x开关充电器评估板实战:从硬件解析到软件调试全攻略

1. 项目概述与核心价值 如果你正在设计一款需要内置单节锂离子电池的便携式设备,比如智能手表、蓝牙耳机或者手持医疗设备,那么电源管理,尤其是电池充电部分,绝对是绕不开的核心挑战。电池不仅要充得快、充得满,还得安…

2026/7/28 16:05:42阅读更多 →
别再被生鲜配送系统低价套路!真实收费标准,菜东家给你透明答案

别再被生鲜配送系统低价套路!真实收费标准,菜东家给你透明答案

做生鲜食材配送的老板都清楚:如今拼价格、拼人脉的时代早已过去,拼效率、拼合规、拼精细化管理才是活下去、赚得到钱的关键。数字化转型不再是可选加分项,而是行业必备生存项。但绝大多数老板第一步就被卡住:生鲜配送系统到底怎么…

2026/7/28 16:05:42阅读更多 →
JAVA练习365- O(1) 时间插入、删除和获取随机元素

JAVA练习365- O(1) 时间插入、删除和获取随机元素

题目概览 实现RandomizedSet 类: RandomizedSet() 初始化 RandomizedSet 对象bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。bool remove(int val) 当元素 val 存在时…

2026/7/28 16:05:41阅读更多 →
图数据结构与算法实战:从基础到工程优化

图数据结构与算法实战:从基础到工程优化

1. 图数据结构基础概念解析 图(Graph)作为数据结构中的"瑞士军刀",是描述实体间复杂关系的终极武器。不同于线性结构的串行排列和树形结构的层级约束,图以节点(Vertex)和边(Edge&…

2026/7/28 16:05:41阅读更多 →
实验报告撰写规范与核心内容梳理指南

实验报告撰写规范与核心内容梳理指南

搞科研的大家!找英文文献依然是科研路上最头疼的一道坎儿吧? 尤其是现在AI工具层出不穷,老工具也在不断升级,选对平台能省下大把时间。今天我给大家盘点8个好用的英文文献检索网站,涵盖传统权威平台 新一代AI智能工具…

2026/7/28 16:05:41阅读更多 →
AI 周报 — 2026 年第 31 周(7 月 20 日 — 7 月 26 日)

AI 周报 — 2026 年第 31 周(7 月 20 日 — 7 月 26 日)

AI 周报 — 2026 年第 31 周(7 月 20 日 — 7 月 26 日)本周概述一、主选资讯(10 条)1. Anthropic 发布 Claude Opus 5:半价逼近 Fable 5,成为 Claude Max 默认模型2. Google 发布 Gemini 3.6 Flash&#x…

2026/7/28 16:03:41阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/28 4:06:39阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:29阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:29阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:29阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/27 16:57:54阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →