二叉树的概念
二叉树的定义
二叉树是有限的结点集合。
- 这个集合或者是空
- 或者由一个根节点和两颗互不相交的称为左子树和右子树的二叉树组成
二叉树的五种基本形态:
- 空树
- 只有根结点
- 左子树为空树
- 右子树为空树
- 左右子树不为空树
特殊的二叉树
满二叉树
- 所有分支结点都有双分支结点;
- 且叶结点都集中在二叉树的最下层。
完全二叉树
- 最多只有下面两层的结点的度数小于2
- 且最下面一层的结点依次排列在最左侧的位置上
完全二叉树实际上是对应的满二叉树删除叶节点层最右边若干个节点得到的。
二叉树的性质
性质1
非空二叉树上叶节点数等于双分支节点数+1。即n0=n2+1.
度之和=分支数
度之和=n1+2n2
分支数=n-1
n=n0+n1+n2
由此得出 n0+n1+n2=n1+2n2 =====>n0=n2+1
求解二叉树的节点个数问题:通常利用二叉树的性质1
性质2
非空二叉树上第i层上至多有2的i-1次方个节点(i>=1)
性质3
高度为h的二叉树至多有2的h-1次方个节点(h>=1)
性质4
完全二叉树性质(含n为节点):
n1=0或者n1=1。n1可由n的奇偶性确定:
n为奇数=>n1=0; n为偶数=>n1=1
若i≤⌊n/2⌋,则编号为i的节点为分支节点,否则为叶节点
除数根节点外,若一个节点的编号为i,则它的双亲结点为⌊i/2⌋
若编号为i的节点有左孩子节点,则左孩子节点的编号为2i;若编号为i的节点有右孩子节点,则右孩子节点的编号为2i+1
二叉树与树、森林之间的转换
森林、树转换为二叉树
一颗树转换成二叉树
首先,我们把所有的兄弟用虚线链接,然后只保留最左边的孩子或唯一一个孩子以外,把剩下的双亲连线删除掉,然后顺时针方向选择45度
多棵树转换为二叉树
首先把每一棵树都转换成二叉树,然后把他们组合到一起,把第二棵树的根节点作为第一棵树根节点的右孩子,第三棵树的根节点作为第二棵树的根节点的右孩子
二叉树还原为森林、树
考察每一个节点的右分支节点,把每一个右分支节点和他的双亲用虚线链接起来,然后删除掉右分支线,再把它逆时针方向旋转45度
将一颗二叉树还原成多颗树
首先我们考察这棵二叉树,我们把根节点的右下节点每个节点对应的那颗树提取出来,也就是说把这一颗二叉树转换为三颗二叉树。
再把这三棵二叉树转化为对应的二叉树
设计一棵二叉树,表示夫妻、父子和兄弟3种关系
二叉树的存储结构
完全二叉树的顺序存储结构
非完全二叉树的顺序存储结构
一般的二叉树先用空节点补全成为完全二叉树,然后对节点编号
二叉树的顺序存储结构的特点
- 对于完全二叉树来说,其顺序存储是十分合适的。
- 对于一般的二叉树,特别是对于那些单分支节点较多的二叉树来说是很不合适的,因为可能只有少数存储单元被利用,特别是对退化的二叉树(即每个分支节点都是单分支的),空间浪费更是惊人。
- 在顺序存储结构中,找一个节点的双亲和孩子都很容易。
二叉树的链式存储结构
借鉴树的孩子链存储结构=》二叉树的链式存储结构
在二叉树的链式存储中,节点的类型定义如下:
typedef struct node
{
ElemType data;
struct node *lchild,*rchild; //左右指针分别指向左右两个孩子
}BTNode;
二叉链存储结构
- 除了指针外,二叉链比较节省存储空间。占用的存储空间与树形没有关系,只与树中结点个数有关。
- 在二叉链中,找一个结点的孩子很容易,但找其双亲不方便。
在二叉链中,空指针的个数?
- n个节点=》2n个指针域
- 分支数为n-1=》非空指针域有n-1个
- 空指针域个数=2n-(n-1)=n+1