树形结构是数据结构中一种非常常用的非线性结构。通常用来表示具备分支关系的层次结构。其中二叉树又是树形结构中最简单最常见的一种。
一、定义
二叉树,顾名思义,只有两个分叉的树,他的特点就是每个节点至多只有两颗子树(即二叉树中不存在度大于2的节点),通常情况下,我们称二叉树的两颗子树为左子树和右子树。二叉树又可递归定义为:①一个空树;②左子树和右子树均为二叉树。换句话说,二叉树有三个部分组成,根节点和同为二叉树的左右子树。这种递归定义非常有趣,它将帮助我们解决很多二叉树的操作问题。
二叉树中有两种特殊的形态,分别是完全二叉树和满二叉树。
满二叉树是指,除叶子节点外,每个节点都有两个子节点,从视觉上讲,就是这颗二叉树被完全填充。
完全二叉树形象上讲是指“最右下角”的节点可能空缺,即只能是最右边且是最大层次的节点空缺。他有两个重要的特点:
①、叶子节点只可能出现在最大的两层上。
②、对任意节点,若其右子树的最大层次为l,那么其左子树的最大层次必定为l或l+1。
二、性质
性质1:在二叉树的第i层至多有2i-1个节点(i>=1),这点有数学归纳法很容易证得。
性质2:深度为k的二叉树至多有2k-1个节点(k>=1),显然,节点最多的情形即为满二叉树。
性质3:对任意一颗二叉树,若其叶子节点(其度为0)数为n0,度为2的节点数为n2,则有n0=n2+1。
证明:设度为1的节点数为n1,那么总结点数n = n0+n1+n2;
设二叉树的分支数为B,由于除了根节点外,每个节点都由一个分支射入,即对应一个分支,即n = B+1。
而每个分支都是有度为1或2的节点射出的,即B = n1+2*n2。
则有n = n1+2*n2+1
综上,有
n0 = n2+1
三、二叉树的遍历
遍历操作是二叉树最重要的操作,其他的操作大都围绕遍历来完成。根据二叉树的递归定义我们可以知道,只要分别完成对二叉树的三个部分的遍历,即可完成对整个二叉树的遍历。
二叉树的遍历通常根据对根节点的访问顺序,分为先序遍历、中序遍历和后续遍历,即先(根)序遍历、中(根)序遍历和后(根)序遍历。以下将详细阐述三种遍历方式。
PreOder(T) = T+PreOder(T的左子树)+PreOder(T的右子树)
InOder(T)=InOder(T的左子树)+T+InOder(T的右子树)
PostOder(T) = PostOder(T的左子树)+PostOder(T的右子树)+T
1、二叉树的链式存储结构:
由二叉树的定义可知,每个节点至少要包含三个部分,即数据、左节点指针、右节点指针。当然,在一些特殊的场合,可能还会有一些其他数据域,如父节点指针、层次、访问标记等。目前暂时考虑最简单的情形。
1 typedef char TElemType; 2 /****二叉树的节点的存储结构****/ 3 typedef struct BiTNode 4 { 5 TElemType data; 6 struct BiTNode *lchild, *rchild; 7 }BiTNode,*BiTree;