详解二叉树的存储王道版(C++/C)

2022-11-18 16:23:51 浏览数 (1)

本篇文章结合王道课程及自己对树的理解,希望对你有所帮助

目录

一、树是什么?

 1.树的概念

2.结点的分类

3.树的其他相关概念

 4.数的存储结构

5、树的常考性质

二、二叉树

1.如何引入二叉树

 2.相互转换

 (1)树转换二叉树

(2)二叉树还原为树​​​​​​​

(3) 森林转化为二叉树

3.二叉树概念

4.二叉树的五种状态

5.几种特殊的二叉树

6.二叉树的性质

7.完全二叉树的常考性质

8.二叉树的存储



一、树是什么?

 1.树的概念

树(Tree)是n(n≥0)个结点的有限集合,当n=0时,为空树;n>0时,为非空树。任意一棵非空树,满足:      

(1)有且仅有一个称之为根的结点;      

(2)除根结点以外的其余结点可分为m(m>0)个互不相交的有限集T1, T2, …, Tm, 其中每一个           集合本身又是一棵树,并且称为根的子树(SubTree)。  

2.结点的分类

关于树的结点涉及许多概念需要我们了解

​​​​​​​结点——结点包含数据元素及若干指向子树的分支信息。 结点的度——结点拥有的子树个数。 树的度——树中结点的最大度数。 终端结点——度为0的结点,又称叶子。 分支结点——度大于0的结点,除了叶子都是分支结点。 内部结点——除了树根和叶子都是内部结点。

属性

结点的层次(深度)-- 从上往下数(默认从1开始) 结点的高度--从下往上数 数的高度 (深度)--  总共多少层 结点的度 -- 有几个孩子(分支) 树的度——各结点的度的最大值

3.树的其他相关概念

路径——树中的俩个结点之间的所经过的结点序列。 路径长度——俩接结点之间路径所经过的边数。 双亲、孩子——结点的子树的根称为该结点的孩子。 兄弟——双亲相同的结点互称兄弟。 堂兄弟——双亲是兄弟的结点互称兄弟。 祖先——即从该结点到数根经过的所有结点,称为该结点的祖先。 子孙——结点的子树中的所有结点都称为该节点的子孙。 有序树——逻辑上看,树中结点的各子树从左至右是有次序的,不能互换。 无序树——逻辑上看,树中结点的各子树从左至右是无次序的,可以互换。 森林——森林是m(m>=0) 棵互不相交的树的集合

 4.数的存储结构

  1.双亲表示法   2.孩子表示法   3.双亲孩子表示法

(这里0表示没有)

如果用这个方法会比较浪费空间,而且a,b方法找孩子或者双亲比较麻烦 

5、树的常考性质

 1) 结点数 = 总度数 1

2) 度为m的树,m叉树的区别 

 3)度为m的树第 i 层至多有m^i-1 个结点(i>=1)

4) 高度为h的m叉树至多有 m^h - 1/ m-1

5) 高度为为h的二叉树至少有h个结点,

     高度为h,度为m的树至少有h m-1个结点。

6) 具有n个结点的m叉树的最小高度为| logm(n(m- 1)   1)]

二、二叉树

1.如何引入二叉树

孩子链表示法

孩子兄弟表示法

孩子兄弟表示法秘诀    长子当做左孩子,兄弟关系左右斜

 2.相互转换

 (1)树转换二叉树

(2)二叉树还原为树

(3) 森林转化为二叉树

3.二叉树概念

二叉树(Binary Tree)是n(n≥0)个结点所构成的集合,它或为空树(n=0);或为非空树。对于非空树T满足:

(1)有且仅有一个称为根的结点;        

(2)除根结点以外,其余结点分为两个互不相交的子集T1和T2,分别称为T的左子树和右子树,且T1和T2本身都是二叉树

4.二叉树的五种状态

5.几种特殊的二叉树

满二叉树完全二叉树

如下图(绿色的为叶子结点)

二叉排序树

可以通过二叉排序树快速的进行查找和插入 

平衡二叉树

6.二叉树的性质

性质1: 

性质2:

性质3 :

7.完全二叉树的常考性质

考点1:

下面这个符号注意不是绝对值,是向上取整的意思 

下面这个符号是向下取整的意思

考点2:

总结

二叉树: no= n2 1 ·第i层至多有2i1个结点( i≥1) ·高度为h的二叉树至多有2h -1个结点 完全二叉树: 具有n个 (n>0)结点的完全二叉树的高度h为|log,(n 1)7或Llog2n] 1 对于完全二叉树,可以由的结点数n推出为0、1和2的结点个数为n、n1和n,(突破点:完全二叉树最多只会有一个度为1的结点)

8.二叉树的存储

几个常考的操作 

 但是如果存储的是非完全二叉树,采用顺序存储会浪费很多空间,所以非完全二叉树基本不考虑这种

 代码

代码语言:javascript复制
struct Elemtype{
	int value;
};

//二叉树的结点

typedef struct BiTNode{
     Elemtype date;  //数据域
     struct BiTNode *lchild ,*rchild;  //左右孩子指针

}BiTNode ,*BiTree;

//定义一个空树
BiTree root = NULL;

//插入根结点
root = (Bitree) malloc(sizeof(BiTnode));
root->date = {1};
root->lchild = NULL; 
root->rchild = NULL;

//插入新的结点
 BiTnode *p = (BiTNode *)malloc(sizeof(BiTNode));
 p->date = {2};
 p->lchild = NULL;
 p->rchild = NULL;
 root->lchild = p;          //作为根结点的左孩子 

 但是这样如果想找到父结点,我们只能从根开始遍历,这样非常浪费时间,我们可以根据题目要求设置一个父结点,也叫三叉链表

代码语言:javascript复制
typedef struct BiTNode{
     Elemtype date;  //数据域
     struct BiTNode *lchild ,*rchild;  //左右孩子指针 
     struct BiTNode *parent;  //父结点

}BiTNode ,*BiTree;

0 人点赞