目录
1、二叉树的定义
二叉树是另一种树形结构,其特点是每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点),并且二叉树的子树有左右之分,其次序不能颠倒。
与树相似,二叉树也以递归的形式定义。二叉树是n(n>=0)个结点的有限集合:
①或者为空二叉树,即n=0。
②或者由一个根节点和两个互不交互的被称为根的左子树和右子树组成。 左子树和右子树又分别是一颗二叉树。
二叉树是有序树,若将其左、右子颠倒,则成为另一棵不同的二叉树。即使树中结点只有一棵子树,也要区分它是左子树还是右子树。二叉树的5种基本形态如图27-1所示。
图27-1 二叉树的五种基本形态
二叉树与度为2的有序树的区别:
①度为2的树至少有3个结点,而二叉树可以为空。
②度为2的有序树的孩子的左右次序是相对于另一个孩子而言的,若某个结点只有一个孩子,则这个孩子就无需区分其左右次序,而二叉树无论其孩子树是否为2,均需确定其左右次序,即二叉树的结点次序不是相对于另一个结点而言,而是确定的。
2、几个特殊的二叉树
2.1、满二叉树
一棵高为h,且含有2^h-1个结点的二叉树称为满二叉树,即树中的每层都含有最多的结点,如图27-2所示。满二叉树的叶子结点都集中在二叉树的最下一层,并且除叶子结点之外每个结点的度数均为2.
可以对满二叉树按层序编号:约定编号从根节点(根节点编号为1)起,自上而下,自左而右。这样每个结点对应一个编号,对于编号为i的结点,若有双亲,则双亲为⌊i/2⌋,若有左孩子,则左孩子为2i;若有右孩子,则右孩子为2i+1。
图27-2 满二叉树
2.2、完全二叉树
高度为h,有n个结点的二叉树,当且仅当每个结点都与高度为h的满二叉树中编号为1~n的结点一一对应时,称为完全二叉树。如图27-3所示。
图27-3 完全二叉树
特点如下:
①若i<=⌊n/2⌋,则结点i为分支结构,否则为叶子结点。
②叶子结点只可能在层次最大的两层出现。对于最大层次的叶子结点,都依次拍列在该层最左边的位置上。
③若有度为1的结点,则只可能有一个,且该结点只有左孩子而无右孩子(重要特性)
④按层序编号后,一旦出现某结点(编号为i)为叶子结点或只有左孩子,则编号大于i的结点均为叶子结点。
⑤若m为奇数,则每个分支结点都有左孩子和右孩子;若n为偶数,则编号最大的分支结点(编号为n/2)只有左孩子,没有右孩子,其余分支结点左右孩子都有。
2.3、二叉排序树
左子树上所有结点的关键字均小于根节点的关键字;右子树上的所有结点的关键字均大于根节点的关键字;左右子树有各是一棵二叉排序树。如图27-4所示
图27-4 二叉排序树
2.4、平衡二叉树
树上任一结点的左子树和右子树的深度之差不超过1。
3、二叉树的性质
1)非空二叉树上的叶子结点树等于度为2的结点树加1.即n0 = n2 + 1;
2)非空二叉树上第k层上至多有2^k-1个结点(k>=1)
第一层至多有2^0=1个结点(也就是根),第2层至多有2^1=2个结点。以此类推,可以证明。
3)高度为h的二叉树至多有2^h-1个结点。
4)对完全二叉树按照从上到下、从左到右的顺序依次编号wei1,2,...,n,则有以下关系:
①当i>1时,结点i的双亲编号为⌊i/2⌋,即当i为偶数时,其双亲的编号为i/2,它是双亲的左孩子;当i为奇数时,其双亲的编号为(i-1)/2,它是双亲的右孩子。
②当2i<=n时,结点i的左孩子编号为2i,否则无左孩子。
③当si+1<=n时,结点i的右孩子编号为2i+1,否则无右孩子。
④结点i所在层次(深度)为⌊log2(i)⌋+1。
5)具有n个(n>0)结点的完全二叉树的高度为⌈log2(n+1)⌉或⌈10g2(n)⌉+1
4、二叉树的存储结构、
4.1、顺序存储结构
二叉树的顺序存储是指用一组地址连续的存储单元依次自上而下、自左而右存储完全二叉树的结点元素,即将完全二叉树上编号为i的结点元素存储在一维数组下标为i-1的空间中。
依据二叉树的性质,完全二叉树和满二叉树采用顺序存储比较合适,树中结点的序号可以唯一地反映结点之间的逻辑关系,这样既能最大可能地节省存储空间,又能利用数组元素的下标值确定结点在二叉树中的位置,以及结点之间的关系。
但对于一般的二叉树,为了让数组下标能反映二叉树中结点之间的逻辑关系,只能添加一些并不存在的空节点,让其每个结点与完全二叉树上的结点相对应,再存储到一维数组的相应分量中。然而,在最坏情况下,一个高度为h且只有h个结点的单支树却需要占据近2^h-1个存储单元。二叉树的顺序存储如图27-5所示。其中0表示并不存在的空结点。
图27-5 二叉树的顺序存储
4.2、二叉树的链式存储
由于顺序存储一般二叉树空间利用率极低,因此二叉树一般都采用链式存储结构,用链表结构来存储二叉树中的每个结点。在二叉树中,结点结构通常包括若干数据域和若干指针域,二叉链表至少包含三个域:数据域data、做指针域lchild、右指针域rchild,如下所示。
lchild | data | rchild |
图27-6所示为常用的二叉链表的存储结构。而实际在不同的应用中还可以再增加某些指针域,如增加指向父结点的指针后,变成三叉链表的存储结构。
图27-5 二叉链表的存储结构
二叉树的链式存储的数据结构描述如下:
typedef struct BiTNode
{
ElmType data;
struct BiTNode *lchild,*rlchild;
}BitNode,*BiTree;
在含有n个结点的二叉链表中,含有n+1个空链域。
解释一下这是为啥:链域和度有一定的联系,n个结点有2n个链域,因为n个结点的树度为n-1,占用了其中n-1个域,则剩余空链域为2n-(n-1) = n+1。