【使用层次序列构建二叉树(数据结构C)】

使用层次序列构建二叉树(C语言实现)

在这里插入图片描述

在数据结构学习过程中,二叉树的构建方式通常有递归建树(前序/中序)层次建树(广度优先)两种。本文将介绍一种基于辅助队列实现的层次建树方法,并结合前序、中序、后序遍历结果来验证构建的正确性。


🌳 示例结构

输入层次序列:a b c d e f g

预期构建出的二叉树结构如下:

        a/   \b     c/ \   / \d   e f   g

🧠 思路解析

层次建树的关键是 广度优先遍历的顺序插入节点。为了实现这一目标,我们需要:

  • 使用一个结构体指针队列,保存待填左右孩子的节点。
  • 每读入一个字符,就创建一个新树节点,并尝试插入到当前队首节点的左或右孩子位置。
  • 如果左右孩子都已填满,就将当前队首出队,指向下一个节点。

🛠️ 关键数据结构

// 树节点结构体
typedef struct BiTNode {char data;struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;// 辅助队列节点(保存 BiTree 指针)
typedef struct tag {BiTNode *p;struct tag *pnext;
} tag_t, *ptag_t;

🧩 核心建树逻辑

BiTree tree = NULL; // 根节点
ptag_t phead = NULL, ptail = NULL, listpnew = NULL, pre = NULL;
char c;while(scanf("%c", &c)) {if(c == '\n') break;BiTree pnew = (BiTree)calloc(1, sizeof(BiTNode));pnew->data = c;listpnew = (ptag_t)calloc(1, sizeof(tag_t));listpnew->p = pnew;if(tree == NULL) {tree = pnew;phead = ptail = listpnew;pre = listpnew;} else {ptail->pnext = listpnew;ptail = listpnew;if(pre->p->lchild == NULL) {pre->p->lchild = pnew;} else if(pre->p->rchild == NULL) {pre->p->rchild = pnew;pre = pre->pnext; // 移动到下一个节点}}
}

🔁 遍历验证

前序遍历(PreOrder):

void PreOrder(BiTree p) {if(p != NULL) {printf("%c", p->data);PreOrder(p->lchild);PreOrder(p->rchild);}
}

中序遍历(InOrder):

在这里插入图片描述

void InOrder(BiTree p) {if(p != NULL) {InOrder(p->lchild);printf("%c", p->data);InOrder(p->rchild);}
}

后序遍历(PostOrder):

void PostOrder(BiTree p) {if(p != NULL) {PostOrder(p->lchild);PostOrder(p->rchild);printf("%c", p->data);}
}

完整代码

//层次建树   借助一个辅助队列
//          a
//        b   c
//    d   e   f   g#include <iostream>
#include<stdio.h>
#include<stdlib.h>//借助辅助队列来进行建树
typedef struct LinkNode{char datac; //数据结点}LinkNode; //建立一个结点//这里没有使用标准的链队列来实现 相应的层次建树
typedef struct {LinkNode *front, *rear;
}LinkQueue;   //建立队列#建立数的结点  使用的是链式的存储typedef struct BiTNode{char data;struct BiTNode *lchild,*rchild;
}BiTNode , * BiTree;//而是建立一个辅助队列 tag
typedef struct tag{
//    BiTree p;  //树的某一结点的地址值BiTNode *p;struct tag *pnext;}tag_t , *ptag_t;//前序遍历
void PreOrder(BiTree p){if(p!=NULL){printf("%c",p->data);PreOrder(p->lchild);PreOrder(p->rchild);}}//中序遍历
void InOrder(BiTree p){if(p!=NULL){InOrder(p->lchild);printf("%c",p->data);InOrder(p->rchild);}}//后序遍历
void PostOrder(BiTree p){if(p!=NULL){PostOrder(p->lchild);PostOrder(p->rchild);printf("%c",p->data);}
}int main() {BiTree pnew; //用来指向新申请的数结点BiTree tree =NULL; //tree 是指向树根的,代表树ptag_t phead= NULL,ptail =NULL, listpnew =NULL, pre =NULL; //初始化队列 定义一个pre 指向执行的当前元素char c;//abcdefwhile(scanf("%c",&c)){if(c=='\n'){break;}//calloc申请空间  大小是两个参数相乘,并对空间进行初始化  赋值为0;//malloc 申请以后还需要对其进行赋值 malloc 返回的是 void * 类型的 也需要进行强制转换树申请结点pnew =(BiTree) calloc(1,sizeof(BiTNode));pnew->data = c;//队列结点申请空间listpnew = (ptag_t) calloc(1,sizeof(tag_t));  //申请一个结构体类型的结点 返回一个指针类型的listpnew->p =pnew;//如果是数的第一个结点if(tree==NULL){tree = pnew;  //tree 指向根的头结点//第一个结点 即是队列头也是 队列尾phead = ptail = listpnew;pre = listpnew; //  用来判断当前结点 的左右孩子是否满了}else {//元素直接入队ptail ->pnext = listpnew;ptail =listpnew;//接下来把元素放入树中if(pre->p->lchild ==NULL){pre ->p ->lchild =pnew;  // pre -> p 左孩子为空 就放入左孩子}else if(pre->p->rchild==NULL){pre->p->rchild =pnew;pre = pre->pnext;  // !!! 左右孩子都满了,指向下一个节点}}}PreOrder(tree);printf("\n");InOrder(tree);printf("\n");PostOrder(tree);return 0;//这没有对树进行相应的输出  ,使用调试发现建树完成
}
//D:\TextOPT\C_CPP_code\For408\DateS\5\SqBinaryTree1\cmake-build-debug\SqBinaryTree1.exe
//123456789
//124895367
//849251637
//894526731

📌 完整输出样例

以输入:abcdefg(按层次顺序输入,以回车结束)为例:

输入:
abcdefg↵输出:
前序遍历:abdecfg
中序遍历:dbeafcg
后序遍历:debgfca

输出对应的树结构:

        a/   \b     c/ \   / \d   e f   g

在这里插入图片描述

✅ 总结

  • 使用辅助队列可以按层次方式构建二叉树,代码逻辑清晰,效率也较高。
  • 在建树过程中,记得及时更新队列指针(例如 pre = pre->pnext;)以避免插入错误。
  • 可结合三种遍历结果验证建树的正确性。

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

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

相关文章

设置Rocky Linux盒盖不休眠的3个简单步骤

在 Rocky linux&#xff08;和其他基于 RHEL 的发行版&#xff09;中&#xff0c;当你关闭笔记本电脑的盖子时&#xff0c;默认行为通常是使系统休眠。如果你想更改这一行为&#xff0c;例如&#xff0c;使系统在关闭盖子时只是锁定&#xff0c;你可以按照以下步骤操作&#xf…

WPF的发展历程

文章目录 WPF的发展历程引言起源与背景&#xff08;2001-2006&#xff09;从Avalon到WPF设计目标与创新理念 WPF核心技术特点与架构基础架构与渲染模型关键技术特点MVVM架构模式 WPF在现代Windows开发中的地位与前景当前市场定位与其他微软UI技术的关系未来发展前景 社区贡献与…

【器件专题1——IGBT第1讲】IGBT:电力电子领域的 “万能开关”,如何撑起新能源时代?

一、IGBT 是什么&#xff1f;重新认识这个 “低调的电力心脏” 你可能没听过 IGBT&#xff0c;但一定用过它驱动的设备&#xff1a;家里的变频空调、路上的电动汽车、屋顶的光伏逆变器&#xff0c;甚至高铁和电网的核心部件里&#xff0c;都藏着这个 “电力电子开关的瑞士军刀”…

新闻速递丨Altair 与 Databricks 达成合作,加速数据驱动型创新

NEWS Altair 近日宣布与数据和人工智能公司 Databricks 达成战略合作&#xff0c;通过新一代数据统一化、图谱驱动智能和企业级人工智能&#xff08;AI&#xff09;技术赋能双方客户。 此次合作整合了两大平台的核心优势&#xff0c;将 Altair RapidMiner 平台的强大功能&…

c++11 :智能指针

目录 一 为什么需要智能指针&#xff1f; 二 智能指针的使用及原理 1. RAII 2. auto_ptr 3. unique_ptr 4. shared_ptr 5. weak_ptr 三 内存泄漏 1.什么是内存泄漏&#xff0c;内存泄漏的危害 2. 如何避免内存泄漏&#xff1f; 一 为什么需要智能指针&#xff1f; …

大模型在直肠癌预测及治疗方案制定中的应用研究

目录 一、引言 1.1 研究背景与意义 1.2 研究目的 1.3 研究方法与创新点 二、大模型技术概述 2.1 大模型的基本原理 2.2 常见大模型类型及特点 2.3 在医疗领域的应用进展 三、直肠癌预测相关数据收集与处理 3.1 数据来源 3.2 数据清洗与预处理 3.3 特征工程 四、大…

VRRP与防火墙双机热备实验

目录 实验一&#xff1a;VRRP负载均衡与故障切换 实验拓扑​编辑一、实验配置步骤 1. 基础网络配置 2. VRRP双组配置 二、关键验证命令 1. 查看VRRP状态 2. 路由表验证 三、流量分析 正常负载均衡场景&#xff1a; 故障切换验证&#xff1a; 实验二&#xff1a;防火…

OpenCV中的SIFT特征提取

文章目录 引言一、SIFT算法概述二、OpenCV中的SIFT实现2.1 基本使用2.1.1 导入库2.1.2 图片预处理2.1.3 创建SIFT检测器2.1.4 检测关键点并计算描述符2.1.5 检测关键点并计算描述符并对关键点可视化2.1.6 印关键点和描述符的形状信息 2.2 参数调优 三、SIFT的优缺点分析3.1 优点…

【信息系统项目管理师】高分论文:论成本管理与采购管理(信用管理系统)

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文1、规划成本管理2、成本估算3、成本预算4、成本控制论文 2019年1月,我作为项目经理参与了 XX基金管理有限公司信用管理系统项目。该项目成 本1000万,建设期为1年。通过该项目,XX基金管理有限公司在信用…

从边缘到云端,如何通过时序数据库 TDengine 实现数据的全局洞

在当今数字化转型加速的背景下&#xff0c;海量的数据生成和实时处理需求已成为企业面临的关键挑战。无论是物联网设备、工业自动化系统&#xff0c;还是智能城市的各类传感器&#xff0c;数据的采集、传输与分析效率&#xff0c;直接影响企业的决策与运营。为此&#xff0c;TD…

Axure全局变量的含义与基础应用

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:全局变量 主要内容:全局变量含义、基础应用 应用场景:元件赋值 案例展示: 案例视频:

题目 3320: 蓝桥杯2025年第十六届省赛真题-产值调整

题目 3320: 蓝桥杯2025年第十六届省赛真题-产值调整 时间限制: 2s 内存限制: 192MB 提交: 549 解决: 122 题目描述 偏远的小镇上&#xff0c;三兄弟共同经营着一家小型矿业公司 “兄弟矿业”。公司旗下有三座矿山&#xff1a;金矿、银矿和铜矿&#xff0c;它们的初始产值分别用…

常见缓存淘汰算法(LRU、LFU、FIFO)的区别与实现

一、前言 缓存淘汰算法主要用于在内存资源有限的情况下&#xff0c;优化缓存空间的使用效率。以确保缓存系统在容量不足时能够智能地选择需要移除的数据。 二、LRU&#xff08;Least Recently Used&#xff09; 核心思想&#xff1a;淘汰最久未被访问的数据。实现方式&#x…

linux ptrace 图文详解(七) gdb、strace跟踪系统调用

目录 一、gdb/strace 跟踪程序系统调用 二、实现原理 三、代码实现 四、总结 &#xff08;代码&#xff1a;linux 6.3.1&#xff0c;架构&#xff1a;arm64&#xff09; One look is worth a thousand words. —— Tess Flanders 相关链接&#xff1a; linux ptrace 图…

Git基本使用(很详细)

一&#xff1a;Git 概述 1.1 定义&#xff1a;分布式版本控制系统 1.2 版本控制 &#xff08;1&#xff09;定义&#xff1a; 版本控制时一种记录文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统 &#xff08;2&#xff09;举例 多副本 优化&#xff1a; 不使用多…

23种设计模式-结构型模式之桥接模式(Java版本)

Java 桥接模式&#xff08;Bridge Pattern&#xff09;详解 &#x1f309; 什么是桥接模式&#xff1f; 桥接模式用于将抽象部分与实现部分分离&#xff0c;使它们可以独立变化。 通过在两个独立变化的维度之间建立“桥”&#xff0c;避免因多维度扩展导致的类爆炸。 &#x…

基于SIMMECHANICS的单自由度磁悬浮隔振器PID控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 单自由度磁悬浮减振器工作原理简介 4.2 SIMMECHANICS工具箱 5.完整工程文件 1.课题概述 基于SIMMECHANICS的单自由度磁悬浮隔振器PID控制系统simulink建模与仿真。其中&#xff0c;SIMMECHANICS是M…

contenthash 持久化缓存

以下是关于持久化缓存(contenthash)的深度技术解析,涵盖原理、配置策略及最佳实践,帮助我们构建高性能前端应用的缓存体系: 一、缓存机制核心原理 1. 浏览器缓存决策矩阵 触发条件缓存行为对应场景URL 未变化 + 强缓存有效直接读取磁盘/内存缓存未修改的静态资源URL 变化…

【前端记事】关于electron的入门使用

electron入门使用 背景how to start第一步 创建一个vite-vue3项目第二步 装各种依赖第三步 配置vite.config.jspackage.jsonelectron入口 启动重写关闭、隐藏、最大化最小化 背景 最近对electron比较感兴趣&#xff0c;折腾一段时间后有了点眉目&#xff0c;记录一下 how to …

跨浏览器音频录制:实现兼容的音频捕获与WAV格式生成

在现代Web开发中&#xff0c;音频录制功能越来越受到开发者的关注。无论是在线会议、语音识别还是简单的语音留言&#xff0c;音频录制都是一个重要的功能。然而&#xff0c;实现一个跨浏览器的音频录制功能并非易事&#xff0c;因为不同浏览器对音频录制API的支持存在差异。本…