树的概念与二叉树的实现

目录

一. 树的概念

二. 访问树的方法

1. 左孩子右兄弟法

2. 双亲表示法

3. 顺序表存孩子的指针(孩子表示法)

 三. 二叉树

1. 二叉树的定义

2. 特殊二叉树

3. 二叉树的性质

4. 存储方式

四. 二叉树的前中后序遍历

1. 前序遍历

2. 中序遍历

3. 后序遍历

4.完整代码


一. 树的概念

树是一种非线性的数据结构,它是由n(n>=0)个有限节点组成的一个具有层次关系的集合。将其称为树是因为,其看起来像一颗翻转的树(根朝上,叶朝下)。最上面的节点是一个特殊的节点,称之为根节点。根节点没有前驱结点,除根节点外,其余节点被分成M(M>0)个互不相交的集合T1、T2、T3……、Tm。其中每一个集合Ti(1<=i<=m)又是一颗结构与树类似的字数。每棵子树的根节点有且只有一个前驱,可以有0个或多个后继,因此树是递归定义

 

不能出现多个节点指向同一节点的情况(如上图)

1. 节点的度一个节点链接了多少子节点,度就为多少
2.叶结点或终端节点度为0的节点,不为0就为分支节点和非终端节点,如上图E、F、G、C、H等

3. 双亲节点或父节点

若一个节点含有子节点,称此节点为其子节点的父节点,如上图A为B\C\D的父节点
4. 孩子节点或子节点一个节点含有的子树的根节点称为该节点的子节点,B\C\D为A的子节点
5. 兄弟节点具有相同父节点的节点互相称为兄弟节点,如上图B\C\D互为兄弟节点
6. 树的度一棵树中最大节点的度称为树的度,如上图,树的度为3

7. 节点的层次

从根开始定义起,根为第一层,根的子结点为第二层,以此类推
8. 树的高度书中节点的最大层次,如上图树的高度为3
9.堂兄弟节点双亲在同一层的节点互为堂兄弟,如上图E和H互为堂兄弟节点
10. 节点的祖先从根到该节点所经分支上的所有节点,上图中A,B是E\F\G的祖先
11. 子孙以某节点为根的子树中任意一个节点都称为该节点的子孙。上图中所有节点都是A的子孙

12. 森林

由m(m>0)棵互不相交的树的集合称为森林

二. 访问树的方法

用一下方法来表示上图中的树

1. 左孩子右兄弟法

链接方式如下图所示

2. 双亲表示法

让每个节点记住其父节点的位置。存储数据元素的节点由两部分组成,1.存储数据元素 2. 存储父节点位置的字段

数组下标节点名称双亲的下标
0A-1(根节点特殊处理)
1B0
2C0
3D1
4E1
5F1
6G2
7H4
8I4
3. 顺序表存孩子的指针(孩子表示法)

由链表和顺序表混合实现

节点定义1.:每个节点包含两部分,数据域来存储数据,另一部分为孩子链表指针,指向一个链表

2.  定义一个顺序表:用来定义存储所有节点的一个数组

3. 定义孩子链表:包含 数据data和指向下一个孩子链表节点的指针next

结果图如下

 三. 二叉树

1. 二叉树的定义

二叉树每个节点最多有两个子节点,被称为左子树和右子树。所有的二叉树都分为三部分:根,左子树,右子树

2. 特殊二叉树

(1) 满二叉树一个二叉树,每层的节点数都达到最大值,如果有k层,节点树为2的k次方-1就是满二叉树,如下图所示

即为满二叉树

(2)完全二叉树:树的高度是h前h-1层都是满的,最后一层不满,在最后一层从左往右都是连续的(满二叉树是特殊的完全二叉树,缺0个节点)如下图所示

即为完全二叉树

3. 二叉树的性质

(1) 若规定根节点层数为1一颗非空二叉树最多有2的(h-1)次方个节点(h为深度)

(2)根节点层数为1深度为h的二叉树最大节点个数为2的n次方-1(满二叉树)

(3)任何一个二叉树,度为0其叶节点个数为N0,度为2的分支节点个数为N2,则有N0=N2+1

(4)若规定根节点层数为1,具有n个节点的满二叉树的深度:h=logN+1(底数为2)

4. 存储方式

分别为用链表存储和用数组存储

数组存储的话可以通过双亲节点与子节点下标间的映射关系来存储二叉树

我们这里用链表来实现

typedef int TreeType;
typedef struct Tree
{TreeType a;struct Tree* left;struct Tree* right;
}Tree;

四. 二叉树的前中后序遍历

1. 前序遍历

先输出根节点再输出左子树再输出右子树

递归实现

void PrevOrder(Tree* root)
{if (root == NULL){printf("NULL ");return;}printf("%d ", root->a);//根PrevOrder(root->left);//左子树PrevOrder(root->right);//柚子树
}

非递归方法实现前序遍历,需要用到栈以及栈的插入,删除,初始化,判空等功能(中序,后序遍历同上)

void PrevOrder2(Tree* root)
{assert(root);ST s;StackInit(&s);Tree* p = root;while (p||!StackEmpty(&s)){if (p != NULL){printf("%d  ", p->a);//输出根StackPush(&s,p);//将"根"存进去p = p->left;//往左子树走}else//左子树走到头{p = StackTop(&s);StackPop(&s);p = p->right;//若此节点还有右子树就执行上面的输出操作,若还是空就来继续pop节点}}
}
2. 中序遍历

先打印输出左子树,再输出根节点再输出右子树

递归实现:

void InOrder(Tree* root)//中序遍历
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);//左子树printf("%d ", root->a);//根InOrder(root->right);//柚子树
}

非递归实现:
 

void InOrder2(Tree* root)
{assert(root);ST s;StackInit(&s);Tree* p = root;while (p || !StackEmpty(&s)){if (p != NULL){StackPush(&s, p);//先存节点,先进去的后出来p = p->left;//找最左边的节点}else//到最左边了{p = StackTop(&s);printf("%d  ", p->a);//输出最左边值StackPop(&s);p = p->right;//往右走看有没有节点}}
}
3. 后序遍历

先打印输出左子树,再右子树,再输出根节点

递归代码:

void PostOrder(Tree* root)
{if (root == NULL){printf("NULL ");return;}PostOrder(root->left);//左子树PostOrder(root->right);//柚子树printf("%d ", root->a);//根
}

非递归代码:

void PostOrder2(Tree* root)
{assert(root);ST s;StackInit(&s);Tree* p = root;Tree* k = root;while (p || !StackEmpty(&s)){while (p != NULL){StackPush(&s, p);p = p->left;//直接走到最左边}p = StackTop(&s);//if (p->right&&p->right!=k)//看是否有右子树{p = p->right;//往右走,循环开始后又会走到此节点的最左边}else{printf("%d  ", p->a);k = p;//将右子树记录下来,否则会死循环p = NULL;//将p置为空,否则循环开始会再次走到最左边StackPop(&s);}}
}
4.完整代码
typedef int TreeType;typedef struct Tree
{TreeType a;struct Tree* left;struct Tree* right;
}Tree;typedef Tree* StackType;typedef struct Stack
{StackType* a;int Top;int capacity;
}ST,*pS;void StackInit(pS pst)
{assert(pst);pst->a = NULL;pst->capacity = 0;pst->Top = 0;
}
void BuyNode(pS pst)
{int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;StackType* tmp = (StackType*)realloc(pst->a, sizeof(StackType) * newcapacity);if (tmp == NULL){perror("relloc fail");return;}pst->a = tmp;pst->capacity = newcapacity;
}
void StackPush(pS pst, StackType data)
{assert(pst);if (pst->Top == pst->capacity){BuyNode(pst);}pst->a[pst->Top] = data;pst->Top++;
}void StackPop(pS pst)
{assert(pst);pst->Top--;//数组里的值不用改,再添加数据会覆盖掉
}StackType StackTop(pS pst)
{assert(pst);return pst->a[pst->Top - 1];
}bool StackEmpty(pS pst)
{assert(pst);return pst->Top == 0;
}void PrevOrder(Tree* root)
{if (root == NULL){printf("NULL ");return;}printf("%d ", root->a);//根PrevOrder(root->left);//左子树PrevOrder(root->right);//柚子树
}
void PrevOrder2(Tree* root)
{assert(root);ST s;StackInit(&s);Tree* p = root;while (p||!StackEmpty(&s)){if (p != NULL){printf("%d  ", p->a);//输出根StackPush(&s,p);//将"根"存进去p = p->left;//往左子树走}else//左子树走到头{p = StackTop(&s);StackPop(&s);p = p->right;//若此节点还有右子树就执行上面的输出操作,若还是空就来继续pop节点}}
}
void InOrder(Tree* root)//中序遍历
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);//左子树printf("%d ", root->a);//根InOrder(root->right);//柚子树
}
void InOrder2(Tree* root)
{assert(root);ST s;StackInit(&s);Tree* p = root;while (p || !StackEmpty(&s)){if (p != NULL){StackPush(&s, p);//先存节点,先进去的后出来p = p->left;//找最左边的节点}else//到最左边了{p = StackTop(&s);printf("%d  ", p->a);//输出最左边值StackPop(&s);p = p->right;//往右走看有没有节点}}
}
void PostOrder(Tree* root)
{if (root == NULL){printf("NULL ");return;}PostOrder(root->left);//左子树PostOrder(root->right);//柚子树printf("%d ", root->a);//根
}
void PostOrder2(Tree* root)
{assert(root);ST s;StackInit(&s);Tree* p = root;Tree* k = root;while (p || !StackEmpty(&s)){while (p != NULL){StackPush(&s, p);p = p->left;//直接走到最左边}p = StackTop(&s);//if (p->right&&p->right!=k)//看是否有右子树{p = p->right;//往右走,循环开始后又会走到此节点的最左边}else{printf("%d  ", p->a);k = p;//将右子树记录下来,否则会死循环p = NULL;//将p置为空,否则循环开始会再次走到最左边StackPop(&s);}}
}int main()
{Tree* a = (Tree*)malloc(sizeof(Tree));a->a = 2;a->left = NULL;a->right = NULL;Tree* b = (Tree*)malloc(sizeof(Tree));b->a = 3;b->left = NULL;b->right = NULL;Tree* c = (Tree*)malloc(sizeof(Tree));c->a = 1;c->left = NULL;c->right = NULL;Tree* d = (Tree*)malloc(sizeof(Tree));d->a = 5;d->left = NULL;d->right = NULL;Tree* e = (Tree*)malloc(sizeof(Tree));e->a = 6;e->left = NULL;e->right = NULL;Tree* f = (Tree*)malloc(sizeof(Tree));f->a = 8;f->left = NULL;f->right = NULL;a->left = b;a->right = c;b->left = d;b->right = e;d->right = f;//PrevOrder2(a);//InOrder(a);//InOrder2(a);//PostOrder(a);PostOrder2(a);//int size = 0;//printf("%d ", size);//printf("\n%d \n", TreeSize(a));//printf("\n%d \n", TreeLeafSize(c));return 0;
}

这篇就到这里啦~

希望能给你带来一些帮助  (๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤

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

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

相关文章

通用型I2C接口的应用之综合应用(N32G45XVL-STB)

通用型I2C接口的应用之综合应用&#xff08;N32G45XVL-STB&#xff09; 目录 概述 1 软硬件接口 1.1 硬件接口 1.2 开发软硬件信息 1.3 SHT-20模块电路 1.4 0.9寸OLED模块介绍 2 驱动接口实现 2.1 SHT20驱动接口 2.2 OLED驱动接口 3 应用接口实现 3.1 软件框架 3.…

C语言基础and数据结构

C语言程序和程序设计概述 程序:可以连续执行的一条条指令的集合 开发过程:C源程序(.c文件) --> 目标程序(.obj二进制文件,目标文件) --> 可执行文件(.exe文件) -->结果 在任何机器上可以运行C源程序生成的 .exe 文件 没有安装C语言集成开发环境,不能编译C语言程…

Open-TeleVision——通过VR沉浸式感受人形机器人视野的远程操作

前言 7.3日&#xff0c;我司大模型机器人(具身智能)线下营群里的一学员发了《Open-TeleVision: Teleoperation with Immersive Active Visual Feedback》这篇论文的链接&#xff0c;我当时快速看了一遍&#xff0c;还是有价值的一个工作(其有受mobile aloha工作的启发)&#x…

锂电池剩余寿命预测 | Matlab基于Transformer的锂电池剩余寿命预测

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab基于Transformer的锂电池剩余寿命预测 Matlab基于Transformer的锂电池剩余寿命预测&#xff08;单变量&#xff09; 运行环境Matlab2023b及以上 NASA数据集&#xff0c;B0005号电池数据训练&#xff0c;B00…

web前端开发——标签一(注释、标题、段落、换行、格式、图片)

今天我来针对web前端开发讲解标签一 目录 html标签_标题&段落&换行 注释标签&#xff1a;Ctrl/ 标题标签&#xff1a; h1-h6 段落标签&#xff1a; 换行标签: 格式标签 图片标签_src属性 html标签_标题&段落&换行 注释标签&#xff1a;Ctrl/ Ctrl/ &…

小程序-设置环境变量

在实际开发中&#xff0c;不同的开发环境&#xff0c;调用的接口地址是不一样的 例如&#xff1a;开发环境需要调用开发版的接口地址&#xff0c;生产环境需要正式版的接口地址 这时候&#xff0c;我们就可以使用小程序提供了 wx.getAccountInfoSync() 接口&#xff0c;用来获取…

查找PPT中某种字体的全部对应文字

本文章的目的是找到某种字体的文字&#xff0c;而不是替换某种字体的文字&#xff0c;也不是将某种字体全部替换为另外一种文字。 第一步&#xff1a;在PPT中按下ALTF11 出现以下窗口 第二步&#xff1a;点击插入->模块 第三步&#xff1a;将以下代码输入到窗体中 Sub F…

树的结构(b,b+树)

无论线性表&#xff0c;栈还是队列&#xff0c;都是一对一&#xff0c;查询的时候&#xff0c;效率较低&#xff0c;数据量比较的大的情况 1.树的定义 一种数据结构&#xff0c;有层次关系的集合&#xff0c;根朝上&#xff0c;叶朝下 除了根节点外&#xff0c;每个子节点都…

论文翻译:Large Language Models for Education: A Survey and Outlook

https://arxiv.org/abs/2403.18105 目录 教育领域的大型语言模型&#xff1a;一项调查和展望摘要1. 引言2. 教育应用中的LLM2.1 概述2.2 学习辅助2.2.1 问题解决&#xff08;QS&#xff09; 2.2.2 错误纠正&#xff08;EC&#xff09;2.2.3 困惑助手&#xff08;CH&#xff09;…

解决elementUI列表的疑难杂症,排序显示错乱的问题

大家好&#xff0c;在使用elementUI表格时&#xff0c;有时会出现一些意料之外的问题&#xff0c;比如数据排序正常但表格显示、排序错乱等。在网上搜索后一般有2种解决方法&#xff1a;1.给表格每一项的el-table-column添加唯一的id用于区分。2.给表格每一项的el-table-column…

羧基聚乙二醇生物素的制备方法;COOH-PEG-Biotin

羧基聚乙二醇生物素&#xff08;COOH-PEG-Biotin&#xff09;是一种常见的生物分子聚合物&#xff0c;具有多种应用&#xff0c;特别是在生物实验、药物研发和生物技术等领域。以下是对该化合物的详细解析&#xff1a; 一、基本信息 名称&#xff1a;羧基聚乙二醇生物素&#x…

数据结构:链表详解 (c++实现)

前言 对于数据结构的线性表&#xff0c;其元素在逻辑结构上都是序列关系&#xff0c;即数据元素之间有前驱和后继关系。 但在物理结构上有两种存储方式&#xff1a; 顺序存储结构&#xff1a; 使用此结构的线性表也叫 顺序表物理存储上是连续的&#xff0c;因此可以随机访问…

电压反馈型运算放大器的增益和带宽

简介 本教程旨在考察标定运算放大器的增益和带宽的常用方法。需要指出的是&#xff0c;本讨论适用于电压反馈(VFB)型运算放大器。 开环增益 与理想的运算放大器不同&#xff0c;实际的运算放大器增益是有限的。开环直流增益(通常表示为AVOL)指放大器在反馈环路未闭合时的增益…

借人工智能之手,编织美妙歌词篇章

在音乐的领域中&#xff0c;歌词宛如璀璨的明珠&#xff0c;为旋律增添了无尽的魅力和情感深度。然而&#xff0c;对于许多创作者来说&#xff0c;编织出美妙动人的歌词并非易事。但如今&#xff0c;随着科技的飞速发展&#xff0c;人工智能为我们带来了全新的创作可能。 “妙…

Cornerstone3D导致浏览器崩溃的踩坑记录

WebGL: CONTEXT_LOST_WEBGL: loseContext: context lost ⛳️ 问题描述 在使用vue3vite重构Cornerstone相关项目后&#xff0c;在Mac本地运行良好&#xff0c;但是部署测试环境后&#xff0c;在window系统的Chrome浏览器中切换页面会导致页面崩溃。查看Chrome的任务管理器&am…

浅析Kafka Streams消息流式处理流程及原理

以下结合案例&#xff1a;统计消息中单词出现次数&#xff0c;来测试并说明kafka消息流式处理的执行流程 Maven依赖 <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-streams</artifactId><exclusio…

【三维AIGC】扩散模型LDM辅助3D Gaussian重建三维场景

标题&#xff1a;《Sampling 3D Gaussian Scenes in Seconds with Latent Diffusion Models》 来源&#xff1a;Glasgow大学&#xff1b;爱丁堡大学 连接&#xff1a;https://arxiv.org/abs/2406.13099 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何…

Spring Security学习笔记(一)Spring Security架构原理

前言&#xff1a;本系列博客基于Spring Boot 2.6.x依赖的Spring Security5.6.x版本 Spring Security中文文档&#xff1a;https://springdoc.cn/spring-security/index.html 一、什么是Spring Security Spring Security是一个安全控制相关的java框架&#xff0c;它提供了一套全…

海外ASO:iOS与谷歌优化的相同点和区别

海外ASO是针对iOS的App Store和谷歌的Google Play这两个主要海外应用商店进行的优化过程&#xff0c;两个不同的平台需要采取不同的优化策略&#xff0c;以下是对iOS优化和谷歌优化的详细解析&#xff1a; 一、iOS优化&#xff08;App Store&#xff09; 1、关键词覆盖 选择关…

用node.js写一个简单的图书管理界面——功能:添加,删除,修改数据

涉及到的模块&#xff1a; var fs require(‘fs’)——内置模块 var ejs require(‘ejs’)——第三方模块 var mysql require(‘mysql’)——第三方模块 var express require(‘express’)——第三方模块 var bodyParser require(‘body-parser’)——第三方中间件 需要…