树的定义
n 个结点的有限集
结点个数为零的书为空树(n = 0);任意一个非空树中有且只有一个特定的称为根的结点。非根的结点可以分为互不相交的有限集,每个集合本身又是一棵树,这些树称为根的子树。
一些基本概念
在树中,结点的度是指节点孩子的个数,树中结点最大的度称为树的度。树的深度是指树有几层。
森林:删除根结点后不相交的树的集合。
树的分类
- 有序树:结点各子树从左至右有序,不能互换(左为第一)
- 无序树:结点各子树可以互换位置。
树中结点总数为n=分支数+1,分支数等于树中各结点的度之和。
树的几种表示方法
孩子表示法
//孩子表示法
typedef struct CTNode{
int child;//链表中每个结点存储的不是数据本身,而是数据在数组中存储的位置下标
struct CTNode * next;
}ChildPtr;
typedef struct {
TElemType data;//结点的数据类型
ChildPtr* firstchild;//孩子链表的头指针
}CTBox;
typedef struct{
CTBox nodes[MAX_SIZE];//存储结点的数组
int n,r;//结点数量和树根的位置
}CTree;
孩子兄弟表示法
#define ElemType char
typedef struct CSNode{
ElemType data;
struct CSNode * firstchild,*nextsibling;
}CSNode,*CSTree;
双亲表示法
#define MAX_SIZE 100//宏定义树中结点的最大数量
typedef char ElemType;//宏定义树结构中数据类型
typedef struct Snode{
TElemType data;//树中结点的数据类型
int parent;//结点的父结点在数组中的位置下标
}PTNode;
typedef struct {
PTNode tnode[MAX_SIZE];//存放树中所有结点
int n;//根的位置下标和结点数
}PTree;
二叉树定义
二叉树是 n (n>=0)个结点所构成的集合。它或为空树(n=0);或为非空树,对于非空树T:有且只有一个结点,除根以外的其余结点分为两个互不相交的子集 T1 和 T2,分别称为 T 的左子树和右子树,且 T1 和 T2 本身又都是二叉树。
二叉树与普通树的异同
二叉树的几种形态
为什么研究二叉树
普通(多叉树)不转换为二叉树,运算很难实现。
为什么重点研究每个结点最多只有两个“叉”的树
- 二叉树的结构最简单,规律最强。
- 可以证明,所有树都能转化为唯一对应的二叉树,不失一般性。
二叉树的性质(重难点)
- 在二叉树的第 i 层上最多有 2i-1 个结点。
- 深度为 k 的二叉树最多有 2k-1 个结点。
- 对于任何一颗二叉树,若 2 度的结点有 n2 个,则叶子树 n0 必定为 n2+1(即 n0 = n2 + 1)。
- 节点数=分支数+1
满二叉树和完全二叉树
完全二叉树的特点
- 叶结点只能出现在最下两层
- 最下层的叶结点一点集中在左部连续位置
- 倒数第二层若有叶结点,一定都在右部连续位置
- 如果结点度为 1,则结点只有右孩子
- 即不存在右子树的情况
- 同样结点树的二叉树,完全二叉树的深度是最小的。
- 具有 n 个结点的完全二叉树的深度为
- 若从上至下、从左到右编号,则编号为 i 的结点,其左孩子编号为 2i ,其右孩子编号必为 2i+1;其双亲编号必为 [i/2]。
二叉树的顺序存储结构
这种顺序存储结构会造成存储空间的浪费。
创建二叉树
二叉树的链式存储结构
三叉树的链式存储结构
二叉排序树(BST)
- 若左子树非空,则左子树上所有值均小于根结点
- 若右子树非空,则右子树上所有值均大于根结点
- 左、右子树也分别是一颗二叉排序树
平衡二叉树(AVL)
定义:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。
高度为N的结点推导公式:Cn=Cn-1+Cn-2+1,C1=1,C2=2
平衡因子:左右子树的高度差