数据结构——树
树的概念
树是一种非线性的数据结构,由n个结点组成且具有一定的层次关系。
树的递归定义
-
树有一个根结点,根节点没有前驱结点。
-
除根节点之外的其余结点被分为若干互补交互的集合,每一个集合构成一颗树,称作子树
-
子树中如果没有结点则称为空树。
树具有如下性质:
-
子树之间不能有交集
-
除了根结点外,每个结点有且仅有一个父节点
-
一棵具有n个结点的树有n-1条边。除了根节点,新添加一个结点便会添加一个边。
树的相关定义
-
结点的度:一个结点含有的子树的个数称为该结点的度。
-
叶结点(终端结点):度为0的结点称为叶结点。
-
分支结点(非终端结点):度不为0的结点。(连接了其余结点)
-
父结点(双亲结点):若一个结点含有子结点,则这个结点称为其子结点的父结点。
-
子结点(孩子结点):一个结点的子树的根结点称为该结点的子结点。
-
兄弟结点:具有相同父节点的结点称为兄弟结点。
-
树的度:树中最大的结点的度称为树的度。
-
结点的层次:定义跟为第一层,跟的子结点定义为第二层,以此类推。
-
树的高度或深度:树中结点的最大层次。
-
堂兄弟结点:父结点在同一层的结点。
-
结点的祖先:从根节点到该结点所经分支上的所有结点。(直接从该结点到根结点上的所有结点)
-
子孙:以某结点为根的子树中任一结点都称为该结点的子孙。
-
森林:由m棵互补交互的树构成的集合。
-
最近公共祖先:距离某些结点最近的祖先(结点的本身也可以成为自己的祖先)
二叉树
二叉树是度为2的树。(由一个根结点和左右子树构成的树)
二叉树的子树有左右之分,次序不能颠倒(故二叉树也是有序树)。
二叉树的几种情况:
-
空树
-
只有根节点
-
只有左子树
-
只有右子树
-
有左右子树
特殊的二叉树:
-
满二叉树 每一个层的结点数都达到最大值(每个除叶结点外的结点都有左右子树) 只有度为0和度为2的结点,并且会满足编号规则
-
完全二叉树 叶子结点只会出现在最后两层 如果有度为1的结点,则只可能有一个,并且只能由左孩子 若有n层,则在n-1层都是满的。
满二叉树是完全二叉树的一种特殊情况。
-
斜树 所有结点都只有左子树或者右子树,只有左子树则称为左斜树,只有右子树则称为右斜树
二叉树的性质:
-
若规定根节点的层数为1,则一课非空二叉树的第i层上最多有2i-1个结点
-
若规定根节点的层数为1,则深度为k的二叉树的最大结点数是2k-1个
-
对任何一课非空二叉树,如果度为0其叶结点个数为n0,度为2的分支结点个数为n2,则有n0=n2+1。
设0,1,2度的结点为n0,n1,n2个。则共有n个,n=n1+n2+n0
又共有n1+2*n2条边,则应该有n1+2n2+1个结点
解得n0=n2+1
-
若规定根结点的层数为1,具有n个结点的完全二叉树的深度floor(log2n)+1(取整)
-
对于具有N个结点的完全二叉树,如果按照从上至下,从左至右的数组顺序对所有结点从0开始编号,则对于序号为i的结点:
-
若i>0,则该结点的父结点序号为(i-1)/2,若i,则无父节点。
推导:父结点=0+2^1+…………2^n+m。
易发现:左孩子和右孩子只差1,对结果无影响(因为是int型),不妨直接讨论左孩子
子结点(左孩子)=0+2^1+…………+2^(n+1)+2*(m-1)+1=2^2+…………2^(n+1)+2m+1
所以子结点-1/2等于父节点
-
若2i+1<N,则该结点的左孩子为2i+1,若2i+1>N,则无左孩子
-
若2i+2<N,则该结点的右孩子为2i+2,若2i+2>N,则无右孩子
-
若完全二叉树结点个数为奇数个,则无度为1的结点,若为偶数,则有1个度为1的结点。且最多就只有1个度为1的结点。
-
二叉树的抽象数据描述
顺序结构进行存储
利用数组进行存储,按照性质中的编号规则进行存储,如果没有该结点,就将该位置给空着。
链式结构进行存储
采用指针来访问子树,采用链表。在结构体中设置左子树指针右子树指针和树中本身的数据。
定义如下:
typedef struct node
{
struct node * left;//指向左子树
struct node * right;//指向右子树
datatype data;//根据相应的要求设置对应的数据类型。
}treenode;