树的概念与二叉树的实现

目录

一. 树的概念

二. 访问树的方法

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.…

vue3 学习笔记08 -- computed 和 watch

vue3 学习笔记08 – computed 和 watch computed computed 是 Vue 3 中用于创建计算属性的重要 API&#xff0c;它能够根据其它响应式数据动态计算出一个新的值&#xff0c;并确保在依赖数据变化时自动更新。 基本用法 squaredCount 是一个计算属性&#xff0c;它依赖于 count…

C语言基础and数据结构

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

常见算法和数据结构(如排序、搜索、链表、树等)。

在计算机科学中&#xff0c;算法和数据结构是解决问题的基石。下面是一些常见的算法和数据结构的简要描述&#xff1a; 常见算法 排序算法&#xff1a; 冒泡排序&#xff1a;通过重复遍历要排序的数列&#xff0c;比较每对相邻元素的值&#xff0c;若发现顺序错误则交换之&am…

Scala学习笔记16: 注解

目录 第十六章 注解1- 常见的Scala注解1.1 标准注解1.2 Java注释 2- 自定义注解3- 注解的使用场景3.1 编译时处理3.2 运行时反射 4- 注解参数end 第十六章 注解 Scala 中的注解 (Annotations) 是一种元编程工具, 用于向编译器、运行时或其他工具提供元数据 ; 注解可以应用于各…

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…

在大型企业级应用中,如何优化 XML 数据的存储和检索效率,以满足高并发访问需求?

在大型企业级应用中&#xff0c;优化XML数据的存储和检索效率可采取以下措施&#xff1a; 数据库选择&#xff1a;选择适合XML存储和查询的数据库&#xff0c;如Oracle、MySQL、PostgreSQL等。这些数据库提供了专门的XML存储和查询功能&#xff0c;能够更高效地处理XML数据。 …

系统Doze白名单常用接口

获取Doze白名单列表&#xff1a;DeviceIdleController.getUserPowerWhitelist是否Doze白名单&#xff1a;DeviceIdleController.isPowerSaveWhitelistAppDoze白名单变化广播:PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED设置Doze白名单&#xff1a;DeviceIdleController.…

【常用知识点-Linux】SSH免密登陆

Author&#xff1a;赵志乾 Date&#xff1a;2024-07-12 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 简介 SSH免密登录是一种基于公钥加密技术的安全认证方式&#xff0c;其原理如下&#xff1a; 生成密钥对&#xff1a;客户端生成一对…

树的结构(b,b+树)

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

【25届秋招备战C++】算法篇-排序算法合集

【25届秋招备战C】算法篇-排序算法合集 一、简介二、解题思路三、模板四、参考 一、简介 排序算法是计算机科学中的基本算法之一&#xff0c;用于将一组数据按照特定的顺序&#xff08;升序或降序&#xff09;进行排列。排序算法广泛应用于数据管理和检索系统&#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;…

第一节变量、运算符、表达式、输入与输出

Hello World package org.wyp;public class Main {//定义了一个类Mainpublic static void main(String[] args) {System.out.println("Hello World");} }变量 byte(字节) 01010111 一个有8位二进制数 每一个0/1叫一位,简称为bit 1byte8bit 一个byte就是一个字节,一…

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

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

昇思训练营打卡第二十四天(LSTM+CRF序列标注)

LSTM&#xff08;Long Short-Term Memory&#xff0c;长短时记忆网络&#xff09;是一种特殊的循环神经网络&#xff08;RNN&#xff09;&#xff0c;由Hochreiter和Schmidhuber在1997年提出。它旨在解决传统RNN在处理长距离依赖问题时出现的梯度消失和梯度爆炸问题。以下是LST…

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

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