1.二叉树、树和森林的定义
(1)树的定义:树是n(n>=0)个结点的有限集。当n=0时,称为空树,任何一棵树都应满足:
①有且仅有一个特定的称为根的结点。
②当n>1时,其余节点可分为m(m>0)个互不相交的有限集T1,T2,...,Tm,其中每个集合本身又是一棵树,并且称为根的子树。
(2)二叉树的定义:二叉树是每个结点最多只有两颗子树,并且二叉树的子树有左右之分,其次序不能颠倒。
(3)森林(forest)的定义:森林是m(m≥0)棵互不相交的树的集合。任何一棵树,删除了根结点就变成了森林。
(4)二叉树和度为2的树的区别:
①度为2的树至少有3个结点,而二叉树可以为空。
②度为2的有序树的孩子的左右次序是相对于另一个海西而言的,若某个结点只有一个孩子,则这个孩子没有左右次序之分;而二叉树无论孩子数是否为2,都有左右次序之分。
(5)树有关常用的公式:
①结点数 = 所有结点的度数 + 1
②度为m的树中第i层上至多有m(i-1) 个结点
③高度为h的m叉树至多有 (mh-1)/(m-1)个结点
④具有n个结点的m叉树的最小高度为┌logm(n(m-1)+1)┐
⑤高度为h的满二叉树的结点数:2h-1
⑥二叉树中n0 = n2 + 1
⑦非空二叉树第k层上至多有2k-1个结点
⑧具有n个结点的完全二叉树的高度为┌log2(n+1)┐
2.二叉树的实现(包括顺序存储结构和链式存储结构)、二叉树的遍历
(1)二叉树的顺序存储结构:
二叉树的顺序存储结构是指用一组地址连续的存储单元依次自上而下、自左至右存储完全二叉树的结点元素,即将完全二叉树上编号为i的结点元素存储在一维数组下标为i-1的分量中。
(2)二叉树的链式存储结构(n个结点的二叉树,有n+1个空链域)
用链表结点来存储二叉树中的每个结点。在二叉树中,结点结构通常包含若干数据域和若干指针域,二叉链表至少包含3个域:数据域data,左指针域lchild,有指针域rchild。
结构体定义:
1 typedef struct BiTree{
2 ElemType data;
3 struct BiTNode *lchild,*rchild;
4 }BiTNode,*BiTree;
(3)二叉树的遍历
①先序遍历(NLR)
1 void PreOrder(BiTree T){
2 if(T!=NULL){
3 visit(T);
4 PreOrder(T->lchild);
5 PreOrder(T->rchild);
6 }
7 }
②中序遍历(LNR)
1 void InOrder(BiTree T){
2 if(T!=NULL){
3 PreOrder(T->lchild);
4 visit(T);
5 PreOrder(T->rchild);
6 }
7 }
③后序遍历(LRN)
1 void PostOrder(BiTree T){
2 if(T!=NULL){
3 PreOrder(T->lchild);
4 PreOrder(T->rchild);
5 visit(T);
6 }
7 }
④层序遍历(依靠队列)
1 void LevelOrder(BiTree T){
2 InitQueue(Q);
3 BiTree p;
4 EnQueue(Q,T);
5 while(!IsEmpty(Q)){
6 DeQueue(Q,p); //出队列,进行遍历
7 visit(p);
8 if(p->lchild != NULL){ //左子树不为空,进队列
9 EnQueue(Q,p->lchild);
10 }
11 if(p->rchild != NULL){ //右子树不为空,进队列
12 EnQueue(Q,p->rchild);
13 }
14 }
15 }
⑤非递归先序遍历
1 void PreOrder(BiTree T){ 2 InitStack(S); 3 BiTree p = T; 4 while(p || !isEmpty(S)){ 5 if(p){ 6 visit(p); 7 Push(S,p); 8 p = p->lchild; 9 }else{ 10 Pop(S,p); 11 p = p->rchild; 12 } 13 } 14 }
3.二叉树结构下的应用及扩展,例如二叉检索树、2-3-4树、Huffman编码以及堆;
(1)二叉检索树(BST)(详见第七章)
中序遍历为有序递增序列
(2)2-3-4树
2-3-4树每个节点最多有四个子节点和三个数据项,名字中 2,3,4 的数字含义是指一个节点可能含有的子节点的个数。对于非叶节点有三种可能的情况:
①、有一个数据项的节点总是有两个子节点;
②、有二个数据项的节点总是有三个子节点;
③、有三个数据项的节点总是有四个子节点;
简而言之,非叶节点的子节点数总是比它含有的数据项多1。如果子节点个数为L,数据项个数为D,那么:L = D + 1
叶节点(上图最下面的一排)是没有子节点的,然而它可能含有一个、两个或三个数据项。空节点是不会存在的。
树结构中很重要的一点就是节点之间关键字值大小的关系。在二叉树中,所有关键字值比某个节点值小的节点都在这个节点左子节点为根的子树上;所有关键字值比某个节点值大的节点都在这个节点右子节点为根的子树上。2-3-4 树规则也是一样。
重点:节点插入和删除,涉及到新建节点和节点分裂。
(3)Huffman编码
定义:在含有n个带权叶结点的二叉树中,其中带权路径长度(WPL)最小的二叉树称为哈夫曼树,也称为最优二叉树。
构造过程:每次选取最小的两个结点,构成一个子树。重复此过程,知道建立一棵完整的数。
哈夫曼编码:构造出哈夫曼树之后,左0右1进行编码,然后每个结点都有唯一编码。
特点:没有一个编码是另一个编码的前缀,则称这样的编码为前缀编码。
带权路径长度(WPL) = ∑(权值*路径长度)
(4)堆(详见第八章堆排序)
大根堆与小根堆。
4.平衡二叉树的定义、平衡因子的定义以及平衡二叉树的旋转操作;
(1)平衡二叉树的定义:为避免树的高度增长过快,降低二叉排序树的性能,规定在插入和删除结点时,要保证任意结点的左、右子树高度差的绝对值不超过1,将这样的二叉树称为二叉平衡树。
(2)平衡因子的定义:定义结点左子树和右子树的高度差为该结点的平衡因子。
(3)平衡二叉树的旋转操作
①LL平衡旋转(右单旋转)
②RR平衡旋转(左单旋转)
③LR平衡旋转(先左后右双旋转)
④RL平衡旋转(先右后左双旋转)
平衡二叉树nh表示深度为h的平衡树中含有的最少结点数,nh = nh-1 + nh-2 +1。 n0=0, n1=1, n2=2
5.树和森林的存储结构、树和森林的遍历以及森林与二叉树的转换;
(1)树的存储结构
①双亲表示法
采用一组连续空间来存储每个结点,同时在每个结点中增设一个伪指针,指示其双亲结点在数组中的位置。
优点:可以很快找到双亲结点
缺点:求结点的孩子结点需要遍历整个结构
②孩子表示法
孩子表示法将每个结点的孩子结点用单链表链接起来形成一个线性结构,此时n个结点就有n个孩子链表。
特点:寻找子女结点非常遍历,查找父母结点需要遍历整个结构。
③孩子兄弟表示法
优点:存储比较灵活,最大的优点是可以方便地实现树转换为二叉树的操作,易于查找结点的孩子等。
缺点:从当前结点查找其双亲结点比较麻烦。
(2)树和森林的遍历
①树的遍历
先根遍历:其遍历序列与这棵树相应二叉树的先序序列相同。
后根遍历:其遍历序列与这棵树相应二叉树的中序序列相同。
②森林的遍历
先序遍历森林:
(1)访问森林中第一棵树的根结点。
(2)先序遍历第一棵树中根结点的子树森林。
(3)先序遍历除去第一棵树之后剩余的树构成的森林。
中序遍历森林:
(1)中序遍历森林中第一棵树的根结点的子树森林。
(2)访问第一棵树的根结点。
(3)中序遍历除去第一棵树之后剩余的树构成的森林。
(3)森林和二叉树的转换
树转换二叉树的规则:做孩子右兄弟。
6.并查集抽象数据类型的定义以及实现
并查集的意义,以及掌握并查集的基本操作的实现。
待学习整理!!!