1.树
1.1 树的概念
树:数是一种非线性的数据结构(逻辑上不是线性的),外形上像一个倒挂的数
实际生活中的数:
数据结构中的树:
数据结构中的数,其实就像实际生活中的树倒看到样子。
1.2树的相关概念
节点的度:每一个节点所含子树的个数,列如A节点的度就是6。
叶节点:节点的度为0的节点,列如B,C等是叶节点。
分支节点:节点的度不为0的节点,列如A,D,E等是分支节点。
一个树是由叶子点和分支节点构成的
父节点:若一个节点含有子节点,那就称这个节点是父亲节点。列如A是B的父节点。
子节点:若一个节点含有子树的根节点,那就称该节点为该根节点的子节点。列如B是A的子节点。
兄弟节点:若两个节点有相同的父节点,那就称这两个节点为互为兄弟节点。列如B和C是兄弟节点。
树的度;树的度就等于所有节点的度中的最大的那个节点的度,列如上面的树最大的节点的度的是A的度,A的度是6,那么树的度就是6。
节点的层次:树的根节点是A,A的层次可以是1或者是0层,根的子节点为2或者1,以此类推。(这里的0或者1是由自己决定的)列如P的节点层次是3或者是4。
空树:没有任何节点的树成为空树。
树的高度或者深度:树中节点的最高层。列如上面这个树的高度是3或者是4.
空树的高度是0或者-1层,这个取决于根节点的层次数。
1.3树的表示方法
这里介绍的是孩子兄弟表示方法
typedef int DateType
struct Node
{
struct* Node leftchild; //左孩子
struct* Node rightbrother; //右兄弟
DateType x; //存储的数据
}
这种方法非常的巧妙,在结构体中只使用了两个指针就能够实现,对于整个树的访问。
该代码实现的逻辑如下:
比如上面的树,根节点A的结构体中存储它的左孩子B,没有右兄弟,接着节点B存储它的左孩子D和它的右兄弟C,以此类推......这个方法的优点是只使用结构体中只使用两个指针就能够实现树的结构,但是是这个实现方法也有它自己的一些缺陷,列如,根节点不能直接找到它的右孩子,必须通过左孩子作为中介才能找到右孩子。
2.二叉树
2.1二叉树的概念
二叉树:二叉树是在树的基础上,进一步规定了,一个根节点最多只能有两个子节点(只能有左孩子和右孩子),二叉树可以为空树。
数据结构中的二叉树:
2.2特殊的二叉树
满二叉树:如果一个二叉树的高度为k,则(k-1)层【包括k-1层】的所有节点都有左孩子和右孩子,所有的节点的总数是(2^k-1)个 。
完全二叉树:完全二叉树与满二叉树相似,只是完全二叉树的第k层的节点没有慢,但还有一个要求就是k层中的节点要依次出现,如下图 ,第k层的节点是依次存在的,若还有一个节点在最右边,那就不能称为使完全二叉树。
满二叉树和完全二叉树:
2.3二叉树的存储结构
2.3.1顺序存储
该存储方式只能用来存储满二叉树和完全二叉树,按每一层由左向右,依次存放在一个一维数组中,但是对于非完全二叉树来说,空节点也需要在数组中占据位置,列如上图不存在4这个节点但是依然需要依次存入(就是数组【3】这个位置不存放数据),这样的方式对于非完全二叉树的存放,会有很多多余的空间消耗。
顺序结构中父节点和子节点的关系
由父节点求子节点
假设父节点在数组中的下标为 i
左孩子在数组中的下标为2*i+1
右孩子在数组中的下标为2*i+2
由子节点求父节点
假设孩子节点在数组中的下标为h(无论是左孩子还是右孩子)
父节点在数组中的下标为(h-1)/2
2.3.2链式存储
链式存储就是直接使用链式结构,这个物理结构和我们的逻辑结构是一致的,很容易理解。
这其中有二叉链和三叉链,二叉链只能支持从父节点找孩子节点,但是不支持孩子节点找父节点;三叉链既支持父节点找孩子节点,也支持孩子节点找父节点。
实现的代码如下
typedef int DateType
//二叉链
struct TreeNode
{
struct Node* leftchild; //左孩子
struct Node* rightchild; //右孩子
DateType x; //存储数据
}
//三叉链
struct TreeNode
{
struct Node* leftchild; //左孩子
struct Node* rightchild; //右孩子
struct Node* parent; //父节点
DateType x; //存储数据
}
总结:
如果有错误请在评论区或者私信指正。