一、考试内容:
1,树和二叉树的定义;
树是一种重要的非线性结构,为具有层次关系和分类关系的数据,提供表示方法。
运用:数据库系统中,用树来组织信息;编译程序中,用树表示源程序的语法结构。
非线性结构特点:每个结点都不只有一个直接前驱和一个直接后继,这些数据结点按分支关系组织起来,清晰地反映了数据元素之间的层次关系。
树(Tree):是n(n≥0)个结点的有限集合,在任一棵树中,有以下两个特性:
1)有且仅有一个特定的称为根(Root)的结点;
2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,…,Tm,其中每一个集合本身又是一棵树,并且称为根的子树(Subtree)。树的定义是递归的。
常用术语&相关概念
- 1、结点的度(degree):该结点拥有的子树的个数。
- 2、叶子或终端结点(leaf):度为0的结点。
- 3、非终端结点或分支结点:度不为0的结点。(除叶子结点)
- 4、树的度:树中各结点度数的最大值。
- 5、树的深度(Depth):树中结点的最大层次。
- 6、森林(Forest):是m(m≥0)棵互不相交的树的集合。对树中的每个结点而言,其子树的集合即为森林。
- 7、满二叉树:一棵深度为k且有2k-1个结点的二叉树称为满二叉树。这种树的特点是每一层上的结点数都
- 是最大结点数。 对满二叉树的结点可以从根结点开始自上向下,自左至右顺序编号。
- 8、 完全二叉树:深度为k,有n个结点的二叉树,当且仅当每个结点的编号正好与深度为k的满二叉树中编号从1到n的结点一一对应时,称之为完全二叉树。 特点:1)叶子结点只可能在层次最大的两层上出现; 2)对任一结点,若其右分支下的子孙的最大层次为l,则其左分支下的子孙的最大层次必为l或l+1。
二叉树的定义:
二叉树是另一种重要的树型结构,它的特点是每个结点至多只有二棵子树,即每个结点的度数不大于2,并且子树有左右之分。递归定义为:二叉树是结点的有穷集合,这个集合或者为空,或者由一个根结点和两棵互不相交的称为左子树和右子树的二叉树组成。
二叉树与无序树是两个完全不同的概念,而且它也不是有序树的特殊情况,因为:
1)无序树的子树不必区分次序;2)有序树中若某结点只有一个孩子则不区分左右次序;
3)二叉树的子树有左右之分,二叉树中某结点即使有一个孩子也要区分左右。
二叉树的性质;
- 性质1 二叉树第i(i≥1)层上至多有2i-1个结点。
- 性质2 深度为k(k≥1)的二叉树至多有2k-1个结点。
- 性质3 在任意二叉树中,若叶子结点(即度为零的结点)个数为n0,度为1的结点个数为n1,度为2的结点个数为n2,那么n0 = n2+1。 n代表二叉树结点的总数,那么 n = n0+n1+n2
- 从二叉树的分支数角度着手。除了根结点外,其余结点都是一个分支进入,B为分支总数,则n=B+1。
- 扩展到树:n0=叶子结点数为:n2+2n3+……+(m-1)nm+1
- 性质4:具有n个结点的完全二叉树树深为 (其中 表示不大于x的最大整数)。
2,树和二叉树的存储结构:
顺序存储结构和链表存储结构。
1. 顺序存储结构 用一组地址连续的存储单元存储二叉树中的元素,要求:把二叉树中的所有结点都安排成一个适当的线性序列,使结点在这个序列中的相互位置能反映出结点之间的逻辑关系。 顺序存储结构仅适用于完全二叉树。
问题: 对完全二叉树既简单又节省空间,但插入、删除不方便;对一般二叉树,要用结点在向量中的相对位置表示结点之间的逻辑关系,也必须按完全二叉树的形式存储树中的结点,这将造成存储空间的浪费。
2. 链表存储结构 是存储二叉树的最自然的方法。根据结点结构的不同,有两种方法: 二叉链表 、三叉链表
1) 二叉链表
表示二叉树的链表中结点应至少包含三个域:数据域,左指针域,右指针域。
类型说明如下:
typedef struct BiTree {
TElemType data;
struct BiTnode *lchild,*rchild;
}BiTnode,*BiTree;
2)三叉链表
有时为了方便找到某结点的双亲,在结点结构中增加一个指向双亲的指针域。
类型说明如下:
typedef struct BiTree {
TElemType data;
Struct BiTnode *lchild,*rchild,*parent;
}BiTnode,*BiTree;
3,二叉树和树的遍历,
遍历二叉树:以一定的次序访问二叉树中的每个结点,并且每个结点仅被访问一次。
访问结点:对结点进行各种操作的简称。例如,查询结点数据域的内容,或输出它的值,或找出结点位置,或是执行对结点的其他操作。 遍历二叉树的过程实质:把二叉树的结点进行线性排列的过程。
LTR:中根遍历二叉树 TLR:先根遍历二叉树 LRT:后根遍历二叉树。
“访问”与“遍历”是两个不同的概念。 “访问”操作是针对一个结点; “遍历”操作是针对一棵树。
4,线索二叉树,
遍历二叉树的实质是把非线性结构线性化,这样可以方便二叉树的许多运算,比如找某结点的前驱或后继,在二叉链表中要找结点的前驱和后继非常困难,所以可以考虑建立另外一种链表,使得在这种链表中可以体现出结点之间的线性有序的前驱和后继关系。这就是线索二叉树。
在线索二叉树中,要求既能体现出结点之间的双亲和孩子结点的关系,又要体现前驱和后继的关系,而且要节省存储空间,所以可以在二叉链表的基础上来建立。
具有n个结点的二叉树,有n-1条边,正是这些边指向其左孩子、右孩子。这意味着在二叉链表的2n个孩子指针域中只用到了n-1个域,还有另外n+1个指针域为空,被闲置。现设法将这些空闲的指针域利用起来。
5,二叉树的层序遍历;
void SeqTraverse(BiTree tree)
{
SeqQueue queue = Init_SeqQueue();
Push_SeqQueue(queue, tree);
while (!IsEmpty_SeqQueue(queue))
{
BiTree root = Pop_SeqQueue(queue);
printf("%c ", root->data);
if (root->lchild)
Push_SeqQueue(queue, root->lchild);
if(root->rchild)
Push_SeqQueue(queue, root->rchild);
}
printf("\n");
}
树、森林遍历和二叉树遍历的对应关系
树 |
森林 |
二叉树 |
先根遍历 |
先序遍历 |
先序遍历 |
后根遍历 |
中序遍历 |
中序遍历 |
6,哈夫曼树及其应用。
哈夫曼树(Huffman)又称最优二叉树,是一类带权路径长度最短的树,有着广泛的应用。
基本概念:
- 1、路径:从树中一个结点到另一个结点的分支构成两结点间的路径。
- 2、路径长度:从树中一个结点到另一个结点的路径上历经的边的数目。
- 3、结点的路径长度:从根结点到该结点的路径上历经的边的数目。
- 4、结点的带权路径长度:从根结点到该结点的路径长度与该结点上权的乘积。
- 5、树的路径长度:从根结点到每一个结点的路径长度之和。 6、树的带权路径长度:从树根到树中所有叶子结点的带权路径长度之和。
n个叶子构成的哈夫曼树其带权路径长度惟一吗?确实惟一。树形惟一吗?不惟一。
为了便于讨论交流在此提倡权值较小的做左子树,权值较大的做右子树。
二、考试要求:
了解树的逻辑结构定义,
掌握二叉树的定义、性质、存储结构和运算,
掌握树和二叉树之间的关系。
在算法实现方面要求,熟练掌握二叉树的递归和非递归遍历,并能够用之解决实际问题,如:计算树的层数、度,查找满足条件的节点等。