二叉树
- 格式:doc
- 大小:601.50 KB
- 文档页数:20
二叉树知识点总结1. 二叉树的性质1.1 二叉树的性质一:二叉树的深度二叉树的深度是指从根节点到叶子节点的最长路径长度。
对于一个空树而言,它的深度为0;对于只有一个根节点的树而言,它的深度为1。
根据定义可知,深度为k的二叉树中,叶子节点的深度值为k。
由此可知,二叉树的深度为所有叶子节点深度的最大值。
1.2 二叉树的性质二:二叉树的高度二叉树的高度是指从根节点到叶子节点的最短路径长度。
对于一个空树而言,它的高度为0;对于只有一个根节点的树而言,它的高度为1。
由此可知,二叉树的高度总是比深度大一。
1.3 二叉树的性质三:二叉树的节点数量对于一个深度为k的二叉树而言,它最多包含2^k - 1个节点。
而对于一个拥有n个节点的二叉树而言,它的深度最多为log2(n+1)。
1.4 二叉树的性质四:满二叉树满二叉树是一种特殊类型的二叉树,它的每个节点要么是叶子节点,要么拥有两个子节点。
满二叉树的性质是:对于深度为k的满二叉树而言,它的节点数量一定是2^k - 1。
1.5 二叉树的性质五:完全二叉树完全二叉树是一种特殊类型的二叉树,它的所有叶子节点都集中在树的最低两层,并且最后一层的叶子节点从左到右依次排列。
对于一个深度为k的完全二叉树而言,它的节点数量一定在2^(k-1)和2^k之间。
2. 二叉树的遍历二叉树的遍历是指按照一定的顺序访问二叉树的所有节点。
二叉树的遍历主要包括前序遍历、中序遍历和后序遍历三种。
2.1 前序遍历(Pre-order traversal)前序遍历的顺序是:根节点 -> 左子树 -> 右子树。
对于一个二叉树而言,前序遍历的结果就是按照“根-左-右”的顺序访问所有节点。
2.2 中序遍历(In-order traversal)中序遍历的顺序是:左子树 -> 根节点 -> 右子树。
对于一个二叉树而言,中序遍历的结果就是按照“左-根-右”的顺序访问所有节点。
2.3 后序遍历(Post-order traversal)后序遍历的顺序是:左子树 -> 右子树 -> 根节点。
数据结构之⼆叉树(BinaryTree)⽬录导读 ⼆叉树是⼀种很常见的数据结构,但要注意的是,⼆叉树并不是树的特殊情况,⼆叉树与树是两种不⼀样的数据结构。
⽬录 ⼀、⼆叉树的定义 ⼆、⼆叉树为何不是特殊的树 三、⼆叉树的五种基本形态 四、⼆叉树相关术语 五、⼆叉树的主要性质(6个) 六、⼆叉树的存储结构(2种) 七、⼆叉树的遍历算法(4种) ⼋、⼆叉树的基本应⽤:⼆叉排序树、平衡⼆叉树、赫夫曼树及赫夫曼编码⼀、⼆叉树的定义 如果你知道树的定义(有限个结点组成的具有层次关系的集合),那么就很好理解⼆叉树了。
定义:⼆叉树是n(n≥0)个结点的有限集,⼆叉树是每个结点最多有两个⼦树的树结构,它由⼀个根结点及左⼦树和右⼦树组成。
(这⾥的左⼦树和右⼦树也是⼆叉树)。
值得注意的是,⼆叉树和“度⾄多为2的有序树”⼏乎⼀样,但,⼆叉树不是树的特殊情形。
具体分析如下⼆、⼆叉树为何不是特殊的树 1、⼆叉树与⽆序树不同 ⼆叉树的⼦树有左右之分,不能颠倒。
⽆序树的⼦树⽆左右之分。
2、⼆叉树与有序树也不同(关键) 当有序树有两个⼦树时,确实可以看做⼀颗⼆叉树,但当只有⼀个⼦树时,就没有了左右之分,如图所⽰:三、⼆叉树的五种基本状态四、⼆叉树相关术语是满⼆叉树;⽽国际定义为,不存在度为1的结点,即结点的度要么为2要么为0,这样的⼆叉树就称为满⼆叉树。
这两种概念完全不同,既然在国内,我们就默认第⼀种定义就好)。
完全⼆叉树:如果将⼀颗深度为K的⼆叉树按从上到下、从左到右的顺序进⾏编号,如果各结点的编号与深度为K的满⼆叉树相同位置的编号完全对应,那么这就是⼀颗完全⼆叉树。
如图所⽰:五、⼆叉树的主要性质 ⼆叉树的性质是基于它的结构⽽得来的,这些性质不必死记,使⽤到再查询或者⾃⼰根据⼆叉树结构进⾏推理即可。
性质1:⾮空⼆叉树的叶⼦结点数等于双分⽀结点数加1。
证明:设⼆叉树的叶⼦结点数为X,单分⽀结点数为Y,双分⽀结点数为Z。
二叉树的几种基本形态二叉树是一种重要的数据结构,在计算机科学和数据结构领域有着广泛的应用。
它由节点和边组成,每个节点最多有两个子节点。
根据节点和边的组合方式,我们可以将二叉树分为几种基本形态。
一、满二叉树满二叉树是指一个二叉树的每个节点都有两个子节点,除了叶子节点。
叶子节点是指没有子节点的节点。
满二叉树是一种特殊的完全二叉树,它的深度为h,节点个数为2^h - 1。
满二叉树具有以下特点:1. 每个节点都有两个子节点,除了叶子节点;2. 所有叶子节点都在同一层;3. 每个非叶子节点都有两个子节点;4. 节点个数为2^h - 1,其中h为深度。
满二叉树的应用非常广泛,例如在堆排序中,堆通常就是满二叉树。
二、完全二叉树完全二叉树是指除了最后一层节点可能不满外,其他层节点都是满的二叉树。
在最后一层,所有的节点都集中在左边。
完全二叉树具有以下特点:1. 最后一层的节点都集中在左边;2. 其他层节点都是满的;3. 如果一个节点有右子节点,则一定有左子节点;4. 节点个数最少为2^(h-1),最多为2^h - 1,其中h为深度。
完全二叉树的应用也非常广泛,例如在二叉堆中,堆通常就是完全二叉树。
三、二叉搜索树二叉搜索树是一种特殊的二叉树,它的左子树中所有节点的值都小于根节点的值,右子树中所有节点的值都大于根节点的值。
同样的规则也适用于每个子树。
二叉搜索树具有以下特点:1. 左子树中所有节点的值都小于根节点的值;2. 右子树中所有节点的值都大于根节点的值;3. 每个子树都符合上述规则;4. 不存在相同节点。
二叉搜索树的应用也非常广泛,例如在数据库中,索引通常就是基于二叉搜索树实现的。
四、平衡二叉树平衡二叉树也称为AVL树,它是一种特殊的二叉搜索树,它的左子树和右子树的高度差不超过1。
这种平衡可以保证二叉树的查找、插入、删除等操作的时间复杂度都是O(log n)。
平衡二叉树具有以下特点:1. 左子树和右子树的高度差不超过1;2. 每个子树都符合上述规则;3. 它是一种特殊的二叉搜索树。
平衡树——特点:所有结点左右子树深度差≤1排序树——特点:所有结点―左小右大字典树——由字符串构成的二叉排序树判定树——特点:分支查找树(例如12个球如何只称3次便分出轻重)带权树——特点:路径带权值(例如长度)最优树——是带权路径长度最短的树,又称Huffman树,用途之一是通信中的压缩编码。
1.1 二叉排序树:或是一棵空树;或者是具有如下性质的非空二叉树:(1)若左子树不为空,左子树的所有结点的值均小于根的值;(2)若右子树不为空,右子树的所有结点均大于根的值;(3)它的左右子树也分别为二叉排序树。
例:二叉排序树如图9.7:二叉排序树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉排序树的存储结构。
中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。
每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。
搜索,插入,删除的复杂度等于树高,期望O(logn),最坏O(n)(数列有序,树退化成线性表).虽然二叉排序树的最坏效率是O(n),但它支持动态查询,且有很多改进版的二叉排序树可以使树高为O(logn),如SBT,AVL,红黑树等.故不失为一种好的动态排序方法.2.2 二叉排序树b中查找在二叉排序树b中查找x的过程为:1. 若b是空树,则搜索失败,否则:2. 若x等于b的根节点的数据域之值,则查找成功;否则:3. 若x小于b的根节点的数据域之值,则搜索左子树;否则:4. 查找右子树。
[cpp]view plaincopyprint?1.Status SearchBST(BiTree T, KeyType key, BiTree f, BiTree &p){2. //在根指针T所指二叉排序樹中递归地查找其关键字等于key的数据元素,若查找成功,3. //则指针p指向该数据元素节点,并返回TRUE,否则指针P指向查找路径上访问的4. //最好一个节点并返回FALSE,指针f指向T的双亲,其初始调用值为NULL5. if(!T){ p=f; return FALSE;} //查找不成功6. else if EQ(key, T->data.key) {P=T; return TRUE;} //查找成功7. else if LT(key,T->data.key)8. return SearchBST(T->lchild, key, T, p); //在左子树继续查找9. else return SearchBST(T->rchild, key, T, p); //在右子树继续查找10.}2.3 在二叉排序树插入结点的算法向一个二叉排序树b中插入一个结点s的算法,过程为:1. 若b是空树,则将s所指结点作为根结点插入,否则:2. 若s->data等于b的根结点的数据域之值,则返回,否则:3. 若s->data小于b的根结点的数据域之值,则把s所指结点插入到左子树中,否则:4. 把s所指结点插入到右子树中。
简述二叉树的五种形态二叉树是一种常用的数据结构,它由节点组成,每个节点最多有两个子节点。
根据节点的分布情况,二叉树可以分为五种形态,分别是满二叉树、完全二叉树、平衡二叉树、搜索二叉树和线索二叉树。
一、满二叉树满二叉树是指除了叶子节点外,每个节点都有两个子节点的二叉树。
也就是说,满二叉树的所有层都是满的,并且最后一层的叶子节点都靠左排列。
满二叉树的节点数可以通过公式计算得到,假设树的高度为h,则节点数为2^h - 1。
满二叉树的特点是结构简单,查找速度快。
在满二叉树中,任意两个节点的路径长度都相同。
二、完全二叉树完全二叉树是指除了最后一层之外,其他层都是满的,并且最后一层的叶子节点都靠左排列的二叉树。
完全二叉树的特点是节点数较少,结构相对简单。
完全二叉树通常用数组来表示,因为它的节点之间的关系可以通过数组的下标来表示。
在完全二叉树中,任意一个节点的左子节点的下标为2i,右子节点的下标为2i+1。
三、平衡二叉树平衡二叉树是指左右子树的高度差不超过1的二叉树。
平衡二叉树的特点是查找、插入和删除的时间复杂度都为O(logn),其中n是节点的数量。
平衡二叉树的高度可以通过节点的平衡因子来计算,平衡因子定义为左子树的高度减去右子树的高度。
平衡因子的取值范围为-1、0和1,当平衡因子的绝对值大于1时,需要通过旋转操作来调整树的平衡性。
四、搜索二叉树搜索二叉树,也称为二叉搜索树或排序二叉树,是一种特殊的二叉树。
它的特点是对于树中的任意一个节点,其左子树中的所有节点都小于它,右子树中的所有节点都大于它。
搜索二叉树的中序遍历结果是一个递增的有序序列。
搜索二叉树的特点是可以快速地查找某个节点,时间复杂度为O(logn),其中n是节点的数量。
但是,如果搜索二叉树不平衡,即左子树或右子树过深,则会导致查找的时间复杂度退化为O(n)。
五、线索二叉树线索二叉树是对二叉树进行了优化的数据结构,它通过添加指向前驱和后继节点的线索,使得遍历操作更加高效。
3.2.5 二叉排序树在这一部分我们要掌握的是二叉排序树的概念、查找、插入和删除操作。
在以下的知识点中,二叉排序树的删除相对于其他知识点要复杂一些,但只要掌握了规则,题目还是很容易解决的。
下面我们先分别给出各部分的介绍及算法实现,再对一些典型题目进行解析。
(1)二叉排序树二叉排序树是一种常用的动态查找表,下面首先给出它的非递归形式。
二叉排序树是一棵二叉树,它或者为空,或者具有如下性质:①任一非终端结点若有左孩子,则该结点的关键字值大于其左孩子结点的关键字值。
②任一非终端结点若有右孩子,则该结点的关键字值小于其右孩子结点的关键字值。
二叉排序树也可以用递归的形式定义,即二叉排序树是一棵树,它或者为空,或者具有如下性质:①若它的左子树非空,则其左子树所有结点的关键字值均小于其根结点的关键字值。
②若它的右子树非空,则其右子树所有结点的关键字值均大于其根结点的关键字值。
③它的左右子树都是二叉排序树。
例如,由关键字值序列(62,15,68,46,65,12,57,79,35)构成的一棵二叉排序树如图3-38所示。
如果对上述二叉排序树进行中序遍历可以得到一个关键字有序序列(12,15,35,46,57,62,65,68,79),这是二叉排序树的一个重要特征,也正是由此将其称为"二叉排序树"。
(2)二叉排序树的查找二叉排序树的结构定义中可看到:一棵非空二叉排序树中根结点的关键字值大于其左子树上所有结点的关键字值,而小于其右子树上所有结点的关键字值。
因此在二叉排序树中查找一个关键字值为k的结点的基本思想是:用给定值k与根结点关键字值比较,如果k小于根结点的值,则要找的结点只可能在左子树中,所以继续在左子树中查找,否则将继续在右子树中查找,依此方法,查找下去,至直查找成功或查找失败为止。
二叉排序树查找的过程描述如下:①若二叉树为空树,则查找失败;②将给定值k与根结点的关键字值比较,若相等,则查找成功;③若根结点的关键字值小于给定值k,则在左子树中继续搜索;④否则,在右子树中继续查找。
假定二叉排序树的链式存储结构的类型定义如下:1.typedef struct linklist{2.keytype key;3.anytype otherelem;4.struct linklist*lchild;5.struct linklist*rchild;6.}Bin_Sort_Tree_Linklist,*Bin_Sort_Tree;二叉排序树查找过程的描述是一个递归过程,若用链式存储结构存储,其查找操作的递归算法如下所示:1.Bin_Sort_Tree_Linklist*bt_search(Bin_Sort_Tree bt,keytype k)2.{∥在根指针为bt的二叉排序树上查找一个关键字值为k的结点,3.∥若查找成功返回指向该结点的指针,否则返回空指针4.if(bt=NULL)‖(bt->key==k)return bt;5.else if(k<bt->key)return bt_search(bt->lchild,k);6.∥在左子树中搜索7.else return bt_search(bt->rchild,k);//在右子树中搜索8.}这个过程也可以用非递归算法实现,算法描述如下:1.Bin_Sort_Tree_Linklist*bt_search1(Bin_Sort_Tree bt,keytype k)2.{3.p=bt;∥指针p指向根结点,搜索从根结点开始4.while(p!=NULL && p->key!=k)5.{6.if(k<p->key)p=p->lchild;7.else p=p->rchild;8.}9.return(p);10.}3)二叉排序树的插入在一棵二叉排序树中插入一个结点可以用一个递归的过程实现。
若二叉排序树为空,则新结点作为二叉排序树的根结点。
否则,若给定结点的关键字值小于根结点关键字值,则插入在左子树上;若给定结点的关键字值大于根结点的值,则插入在右子树上。
下面是二叉排序树插入操作的递归算法。
1.void bt_insert1(Bin_Sort_Tree*bt,Bin_Sort_Tree_Linklist*pn)2.{∥在以bt为根的二叉排序树上插入一个由指针pn指向的新的结点3.if(*bt=NULL)*bt=pn;4.else if(*bt->key>pn->key)bt_insert 1(&(*bt->lchild),pn);5.else if(*bt->key<pn->key)bt_insert1(&(*bt->rchild),pn);6.}这个算法也可以用非递归的形式实现,如下所示:1.void bt_insert 2(Bin_Sort_Tree*bt,2.Bin_Sort_Tree_Linklist*pn)3.{4.p=bt;5.while(p!=NULL && p->key!=pn->key)6.{7. q=p;8.if(p->key>pn->key)p=p->lchild;9.else p=p->rchild;10.}11.if(p=NULL){12.if(q->key>pn->key)q->lchild=pn;13.else q->rchild=pn->key;14.}15.}利用二叉排序树的插入算法,可以很容易地实现创建二叉排序树的操作,其基本思想为:由一棵空二叉树开始,经过一系列的插入操作生成一棵二叉排序树。
例如,由结点关键字序列(62,15,68,46,65,12,57,79,35)构造二叉排序树的过程为:从空二叉树开始,依次将每个结点插入到二叉排序树中,在插入每个结点时都是从根结点开始搜索插入位置,找到插入位置后,将新结点作为叶子结点插入,经过9次的插入操作,建成由这9个结点组成的二叉排序树。
创建二叉排序树的算法如下:1.Bin_Sort_Tree_Linklist*bt_bulid(Bin_Sort_Tree a,int n)2.{∥在数组a的a[1]~a[n]3.单元中存放着将要构成二叉排序树的n个结点内容4.bt=NULL;5.for(i=1;i<=n;i++)6.{7.p=(Bin_Sort_Tree_Linklist*)malloc8.(sizeof(Bin_Sort_Tree_Linklist));9.p->key=a[i].key;10.p->otherelem=a[i].otherelem;;11.p->lchile=NULL;12.p->rchile=NULL;13.bt_insert1(&bt,p);14.}15.return(bt);16.}(4)二叉排序树的删除下面分四种情况讨论一下如何确保从二叉树中删除一个结点后,不会影响二叉排序树的性质:①若要删除的结点p为叶子结点,可以直接进行删除。
②若要删除结点p有右子树,但无左子树,可用其右子树的根结点取代要删除结点的位置。
③若要删除结点p有左子树,但无右子树,可用其左子树的根结点取代要删除结点的位置,与步骤②类似。
④若要删除结点p的左右子树均非空,则在其左子树中找到最右结点r来代替被删的结点(即将r所指结点的右指针置成p所指结点的右子树的根,然后用p所指结点的左子树的根结点代替被删的p所指结点)。
可以按下述方法来查找到左子树中的最大元素值的结点:首先移动到子树的根,然后沿着各节点的右孩子指针移动,直到右孩子指针为0为止,此时找到的结点即为左子树中的最大元素值的结点。
下面是二叉排序树删除算法的实现:1.void delnode(btree*b,int x)2.{3.btree*p,*q,*r,*t;4.p=b;5.q=NULL;6.while(p!=NULL && p->data!=x)7.if(x<p->data)8.{9. q=p;10.p=p->left;11. }12.else13. {14.q=p;15.p=p->right;16. }17.if(p==NULL)pintf("未发现数据域为%d的结点\\n",x);18.else if(p->left==NULL)19. {20.if(q==NULL)t=p->right;21.else if(q->left==p)q->left=p->right;22.else q->right=p->right;23. }24.else/*被删结点有左子树*/25./*查找被删结点左子树中的最右结点,即刚好小于x的结点*/26. {27.r=p->left;28.while(r-right!=NULL)29. r=r-right;30./*被删结点的右子树作为r的右子树*/31.r-right=p->right;32./*被删结点的左子树根代替被删结点*/33.if(q==NULL)t=p->left; /*被删结点是根结点*/34.else if(q->left==p)q->left=p->left;35.else q->right=p->left;36. }37.}【习题及解析】【例3-34】二叉树为二叉排序树的()条件是其任一结点的值均大于其左孩子的值,小于其右孩子的值。
A.充分不必要B.必要不充分C.充分必要D.既不充分也不必要【分析】本题考查二叉排序树的定义。
由二叉排序树的定义可知,在二叉排序树中,任一非终端结点的关键字的值大于其左子树中所有结点的关键字的值(当然也大于其左孩子的值),小于右子树中所有结点的关键字的值(当然也小于其右孩子的值)。
分析至此,我们知道该题的选项中至少应该包括必要条件,故A、D可以排除。
下面我们看是否充分,也即满足题干要求的二叉树是否一定是二叉排序树。
我们可以用反证法,举出一个例子证明满足题干要求的二叉树不一定是二叉排序树。
图3-39所示的二叉树满足题干的要求,54,46,但显然这不是一棵二叉排序树,其中序遍历序列为4,6,5,并非一个单增或单减的序列。
故正确答案中不应包含充分条件,排除C。
所以本题应该选B。
【解答】B。
【例3-36】已知一棵二叉排序树,其结构如图3-42a所示。
画出依次删除关键字为a1=13,a2=12,a3=4,a4=8的各个结点后,该二叉排序树的结构。