5.1.1 树的基本定义
非空树的特性:
(1)有且仅有一个根节点
(2)没有后继的结点称为“叶子结点”(或终端结点)
(3)有后继的结点称为“分支结点”(或非终端结点)
(4)除了根节点外,任何一个结点都有且仅有一个前驱
(5)每个结点可以有0个或多个后继
基本概念:
(1)空树:节点数为0的树
(2)子树
结点、树的属性描述
(1)结点的层次(深度):从上往下数,默认从1开始
(2)结点的高度:从下往上数
(3)树的高度(深度):总共有多少层
(4)结点的度:有几个分支
(5)数的度:各结点的度的最大值
有序树&无序树
从左到右是否是有次序的
森林
m棵互不相交的树的集合
5.1.2 树的性质
(1)结点树=总度数+1
(2)度为m的树&m叉树
- 度为m的树:任意节点度≤m;至少一个结点的度=m;一定是非空树,至少有m+1个结点
- m叉树:任意节点度≤m;允许所有结点的度<m;可以是空树
(3)度为m的树&m叉树第i层至多有m^(i-1)个结点
(4)高度为h的m叉树,最多有个结点(等比数列求和)
(5)高度为h的m叉树至少有h个结点。高度为h、度为m的树至少有h+m-1个结点。
(6)具有n个结点的m叉树的最小高度为
- 所有结点都有m个结点,则
5.2.1 二叉树定义
基本概念:
- 空二叉树
- 由一个根结点和两个互不相交的被称为根的左子树和右子树组成。左子树和右子树又分别是一棵二叉树。
特点:
- 每个结点至多只有两棵子树
- 左右子树不能颠倒(二叉树是有序树)
- 二叉树是递归定义的数据结构
二叉树的五种状态:
- 空二叉树
- 只有左子树
- 只有右子树
- 只有根结点
- 左右子树都有
几个特殊的二叉树:
(1)满二叉树:
概念:一棵高度为h,且含有个结点的二叉树
特点:
- 只有最后一层有叶子结点
- 不存在度为1的结点
- 按层序从1开始编号,结点i的左孩子为2i,右孩子为2i+1;结点i的父节点为[ i/2 ](如果有的话)
(2)完全二叉树:
概念:当且仅当其每个结点都与高度为h的满二叉树中编号为1~n的结点一一对应时,称为完全二叉树
特点:
- 只有最后两层可能有叶子结点
- 最多只有一个度为1的结点
- 按层序从1开始编号,结点i的左孩子为2i,右孩子为2i+1;结点i的父节点为[ i/2 ](如果有的话)
- i≤[ n/2 ]为分支结点,i>[ n/2 ]为叶子结点
- 如果某结点只有一个孩子,那么一定是左孩子
(3)二叉排序树
空二叉树,或者是具有如下性质的二叉树:
- 左子树上所有结点的关键字均小于根结点的关键字;
- 右子树上所有结点的关键字均大于根结点的关键字。
- 左子树和右子树又各是一棵二叉排序树。
(4)平衡二叉树
树上任一结点的左子树和右子树的深度之差不超过1。
平衡二叉树能有更高的搜索效率。
5.2.2 二叉树的性质
(1)二叉树性质
- 1.设非空二叉树中度为0、1和2的结点个数分别为n0、n1和n2,则n0=n2+ 1(叶子结点比二分支结点多一个)【k+1层满二叉树:n0=2^k,n2=2^k-1】
假设树中结点总数为n,则n=n0+n1+n2
也有,n=n1+2*n2+1 (树的结点数=总度数+1)
- 2.二叉树第i层至多有2^(i-1)个结点(m叉树第i层至多有m^(i-1)个结点)
- 3.高度为h的m叉树,最多有
个结点(等比数列求和)(m=2)
(2)完全二叉树的性质
1、具有n个(n> 0)结点的完全二叉树的高度h为或者
2、对于完全二叉树,可以由的结点数n推出度为0、1和2的结点个数为n0、n1和n2
完全二叉树最多只有一个度为1的结点,即n1=0或1,由n0=n2+ 1 知 n0+n2一定是奇数
- 若完全二叉树有2k个(偶数)个结点,则必有n1=1,n0=k,n2=k-1
- 若完全二叉树有2k-1个(奇数)个结点,则必有n1=0,n0=k,n2=k-1
5.2.3 二叉树的存储结构
顺序存储与链式存储
1 顺序存储
1)定义长度为maxsize的数组,从上到下,左到右存储完全二叉树的各个结点。
2)让第一个位置,即下标为0处空缺,保证数组下标和结点编号一致。
3)初始时标记所有位置为空
#define MaxSize 100
struct treenode{
int value; //elem type;结点中的数据元素
bool isempty; //结点是否为空
}
treenode t[MaxSize]; //2)
for (int i=0;i<MaxSize;i++){
t[i].isempty=true;
}//3)初始时标记所有位置为空
常考:完全二叉树按顺序存储
1)i的左孩子:2i
2)i的右孩子:2i+1
3)i的父节点:[i/2]
4)i所在的层次: 或者
若不是完全二叉树,则无法从结点编号反映逻辑关系。
二叉树的顺序存储,需要把结点编号和完全二叉树对应起来;
最坏的情况:高度为h且只有h个结点的单支树,至少需要 个存储单元。
2 链式存储
//链式存储
struct ElemType{
int value;
}
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
//定义一颗空树
BiTree root=NULL;
//插入根节点
root=(BiTree) malloc(sizeof(BiTNode));
root->data={1};
root->lchild=NULL;
root->rchild=NULL;
//插入新结点
BiTNode *p=(BiTNode *) malloc(sizeof(BiTNode))
p->data={2};
p->lchild=NULL;
p->rchild=NULL;
root->lchild=p; //p作为根节点的左孩子
//...
【注】n个结点的二叉树链表共有n+1个空链域
why:n个结点,有2n个指针,n-1条线段,故有n+1个空链域。(可以构造线索二叉树)
上述链式存储,在找父节点时只能从根节点遍历;
三叉链表:加入父结点指针(根据实际需要)。
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
struct BiTNode *parent;
}BiTNode,*BiTree;