树与二叉树 —— 十分钟吊打数据结构

简介: 树的的概念与结构🤔树是个甚么?和现实中的数差不多,有根有茎有枝有叶,长的和向下延伸的树根差不多,也可以看成一棵倒立的树,==树是一种非线性数据结构,由 n(n>=0)个有限节点组成一个具有层次关系的集合,具象一下就类似这样:

image.png

他有一个特殊的节点,称为根节点,也就是上图的 A 节点,除根节点外其余节点都被分成 M 个不相交的集合,每个集合又是一棵结构与树类似的子树,每棵子树根节点有且只有一个,后继节点可以是 0 个或者多个。因此,树是递归定义的。


这里就又需要思考递归的含义,递归是当前问题和子问题的集合,这里的树是根和n个子树构成,而每个子树的结构又是如此,开始逐渐套娃,直到遇到“叶子”结束。


注意,树与非树的区别就在于:


树结构的子树是互不相交的(带回路的结构叫图)

除了根节点外,其余节点有且仅有一个父节点

一颗有N个节点的数有N-1条边


基本术语🤔

不理解这些基本概念后面没法玩儿捏,还是得知道怎么去描述:


结点的度:结点的子树个数;

树的度:树的所有结点中最大的度数;

父结点:有子树的结点是其子树的根节点的父结点;

子结点:若A结点是B结点的父结点,则称B结点是A结点的子结点;

兄弟(姐妹)结点:具有同一个父结点的各结点彼此是兄弟结点(还有堂兄弟(姐妹)节点,自己意会就行懒得打字);

祖先结点:沿树根到某一结点路径上的所有结点

子孙结点:某一结点的子树中的所有结点

结点的层次:规定根结点在1层,其他任一结点的层数是其父结点的层数加1;

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

树的表示🤔

树要进行表示可不好表示,因为有一个大问题——子节点个数不确定。


这里树必然是一个链式结构,每个节点都有存的值以及指向孩子的指针,现在我们所使用的结构大多为顺序表,有人会用数组来搞(下标为孩子个数),也可以使用C++语法的 vector 来进行操作,但这些都只能算是中规中矩,这里介绍一种很优秀的表示方法可以不用关心度的多少和空间的消耗:孩子&兄弟表示法。


在强调一遍,这个结构表示树是最优秀的,没有之一!

typedef int datatype;
struct node
{
struct node* first;//第一个孩子节点
struct node* next;//指向下一个兄弟节点
datatype data;//数据域
}

来说明一下,随便以一个数结构为例:

image.png

A 的第一个孩子是B,则 first 指向B,而 A 的其他孩子怎么办呢?A 会先抛开不管,父母的二胎总喜欢叫老大来带,压力来到了 B 的身上, B 的 next 指向他的兄弟节点 C,也就是 A 的另一个孩子, C 没有兄弟了,就可以甩手无后顾之忧,他的 next 指向 NULL。


总结一下就是父亲指向第一个孩子,其余的都用孩子的兄弟指针链接起来即可,掌握了这个道理,无论多少孩子都无所谓,随便你玩儿

树的实际应用🤔

树可以用来表示文件系统的目录树结构,比如最常见的:

image.png


其实这只是一种显示方式,目录树要依赖于其他主体,并不是内容本身,在Word ,Excel,Notepad++ 等平台都是不一样的。

二叉树🤔

二叉树这位重量级,各位多多少少有所耳闻吧,今天就换他来认识认识你。

二叉树就是一个度为 2 的树,即每个节点最多有两个子节点,当然,二叉树存在两个子节点时,节点有左右之分,顺序是绝对的,因此二叉树也是个有序树。

这里也介绍一下几个特殊的二叉树:

1. 斜二叉树

image.png

2. 满二叉树

image.png

每一层的节点都到达了最大值,层数为 n,那他的节点数就是 2^n-1 个(本质就是一个等比数列)。

3. 完全二叉树

image.png

这是一种效率贼高的数据结构,满二叉树是特殊的完全二叉树,完全二叉树由满二叉树引申出来,即(n-1)层都是满的,最后一层不满,但必须是从左到右挨的严严实实的。他们的优势就是用来表示一种数据结构——堆。


那么问题来了,现在这里存了一堆数,这一堆数中谁是谁的左孩子,谁又是谁的右孩子呢?


我们用数学关系是可以表示出来的,益父子节点的下标为关系计算:


父节点 = (子节点-1)/2;

左孩子节点:父节点 * 2 +1;

右孩子节点:父节点 * 2 + 2;


你可能会疑惑为什么父节点没有根据左孩子和右孩子来计算,原因很简单,不管是奇数还是偶数,相邻两个减1除2的结果是相同的。


二叉树的性质🤔

若规定根节点的层数为1,则一棵非空二叉树的第 n 层最多有2^(n-1)个节点;

若规定根节点的层数为1,则深度为 h 的二叉树最大结点数为 (2^h) -1;

任意二叉树,度为0的节点比度为 2 的节点永远多 1 个;

具有n个节点的完全二叉树深为log2x+1(其中x表示不大于n的最大整数);

如果对一颗有n个结点的完全二叉树(其深度为[log2n]+1)的结点按层序编号(从第一层到[log2n]+1层,每层从左到右),对任一结点i(1<= i <=n):

(1)如果i=1,则结点i是二叉树的根,无双亲,如果i>1,则其双亲结点是结点 i/2

(2)如果2i>n,则结点i无左孩子(结点i为叶子结点)否则左孩子是结点 2i。

(3)如果2i+1>n,则结点i无右孩子,否则其右孩子是结点2i+1。

相关文章
|
11天前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
49 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
11天前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
36 12
|
11天前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
36 10
|
11天前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
34 2
|
25天前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
283 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
44 1
|
11天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
127 75
|
11天前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
34 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
11天前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
35 9

热门文章

最新文章