目录
5.1 树的基本概念
5.1.1 树的定义
树是n个结点的有限集。当n=0时,称为空树。在任意一棵非空树中应满足:
- 有且仅有一个特定的称为根的结点。
- 当n>1时,其余结点可分为m个互不相交的有限集{T},集合本身又是一棵树,并且称为根的子树。
显然,树的定义是递归的,即在树的定义中又用到了其自身,树是一种递归的数据结构。书作为一种逻辑结构,同时也是一种分层结构,具有以下两个特点:
- 树的根结点没有前驱,除根结点外的所有结点有且仅有一个前驱。
- 树中所有结点可以有零个或多个后继。
5.1.2 树的几种术语
- 树中一个结点的孩子个数称为该结点的度,树中最大度数称为树的度。
- 结点的深度是从根结点开始自顶向下逐层累加。
- 结点的高度是从叶结点开始自底向上逐层累加。
- 树的高度/深度是树中最大的深度/高度。
- 树的路径长度是指树根到每个结点的路径长的总和。
5.1.3 树的性质
- 树中结点数n等于所有结点的度数之和加1。
- 度为m的树(即m叉树)中第i层上至多有个结点。
- 高度为h的m叉树至多有个。
- 具有n个结点的m叉树最小高度为。
5.2 树的表示
5.2.1 树的存储结构
1. 树的顺序存储---双亲表示法
//树的顺序存储法(双亲表示法)
#define MAX_Tree_Size 100//树的最多结点数
typedef struct{ //树的结点定义
Elemtype data;
int parent;
}PTNode;
typedef struct {// 树的类型定义
PTNode nodes[MAX_Tree_Size];
int n;//树的结点数
}PTree;
2. 孩子表示法
3. 二叉链表表示法---树的兄弟表示法
//树的兄弟表示法--二叉链表表示法
typedef struct CSNode {
Elemtype data;
struct CSNode* firstchild, * nextibling;//第一个孩子和右兄弟指针
}CSNode, * CSTree;
5.3 树的遍历
5.3.1 先根遍历
- 若树非空,访问根结点。
- 依次遍历子树并遵循先根后结点的原则。
对应二叉树的先序遍历:
- 先访问完根结点再依次访问左结点(树的孩子结点)和右结点(树的根结点)。
//树的先根遍历
void PreOrder(TreeNode* R)
{
if (R != NULL)
visit(R);
while (R还有下一个子树T)
PreOrder(T);
}
5.3.2 后根遍历
- 先遍历同一结点不同孩子。
- 再访问双亲结点
对应二叉树中序遍历为:
- 访问完根结点(树双亲结点)再问右孩子(树的兄弟结点为根结点)。
- 访问完左子树(树的孩子结点)访问根结点。
//树的后根遍历
void PostOrder(TreeNode* R)
{
if (R != NULL) {
while (R还有下一个子树)
PostOrder(T);
visit(R);
}
}
5.4 二叉树
5.4.1 二叉树的定义
m=2的树即为二叉树,它有着所有有关树的定义;二叉树是有序树,若将左右子树颠倒,则成为另一颗完全不同的二叉树。即使树中的结点只有一棵子树,也要区分它是左子树还是右子树。二叉树可以为一颗空树。