二叉树是一种特殊的树,在二叉树中每个节点最多有两个子节点,一般称为左子节点和右子节点(或左孩子和右孩子),并且二叉树的子树有左右之分,其次序不能任意颠倒。
树的术语:
Name | Function |
---|---|
路径 | 顺着连接点的边从一个节点走向另一个节点,所经过的节点的顺序排列就称为路径。 |
根 | 树顶端的节点就称为根,一棵树只有一个根,如果要把一个节点和边的集合定义为树,那么从根到其他任何一个节点都必须有一条路径。 |
父节点 | 每个节点(除了根)都恰好有一条边向上连接到另一个节点,上面的节点就称为下面节点的“父节点”。 |
子节点 | 每个节点都可能有一条或多条边向下连接其他节点,下面的这些节点就称为它的“子节点”。 |
叶节点 | 没有子节点的节点称为“叶子节点”或简称“叶节点”。树只能有一个根,但是可以有很多叶节点 |
子树 | 每个节点都可以作为子树的根,它和它所有的子节点,子节点的子节点等都含在子树中。 |
访问 | 当程序控制流程到达某个节点的时候,就称为“访问”这个节点,通常是为了在这个节点处执行某种操作,例如查看节点某个数据字段的值或者显示节点。 |
遍历 | 遍历树意味着要遵循某种特定的顺序访问树中的所有节点。 |
层 | 一个节点的层数是指从根开始到这个节点有多少“代”。 |
关键字 | 可以看到,对象中通常会有一个数据域被指定为关键字值。这个值通常用于查询或者其他操作。 |
二叉树 | 如果树中的每个节点最多只能有两个子节点,这样的树就称为“二叉树”。 |
满二叉树:在一棵二叉树中,如果所有分支结点都有左孩子和右孩子结点,并且叶子结点都集中在二叉树的最下层,这样的树叫做满二叉树
如:
根据满二叉树的定义,得到其特点为:
- 叶子只能出现在最下一层。
- 非叶子结点度一定是2.
- 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。
完全二叉树:若二叉树中最多只有最下面两层的结点的度数可以小于2,并且最下面一层的叶子结点都是依次排列在该层最左边的位置上,则称为完全二叉树。
如:
满二叉树与完全二叉树的区别:满二叉树是完全二叉树的特例,因为满二叉树已经满了,而完全并不代表满。所以形态你也应该想象出来了吧,满指的是出了叶子节点外每个节点都有两个孩子,而完全的含义则是最后一层没有满,并没有满。
结合完全二叉树定义得到其特点:
- 叶子结点只能出现在最下一层和次下层(满二叉树继承而来)
- 最下层叶子结点一定集中在左 部连续位置。
- 倒数第二层,如有叶子节点,一定出现在右部连续位置。
- 同样结点树的二叉树,完全二叉树的深度最小(满二叉树也是对的)。
一般二叉树的性质:
- 左节点下标是其父节点的二倍,右节点的下标是其父节点的二倍加一(左节点加一)。
- 第n层的节点个数最多为2n-1。
- 前n层的节点个数最多为2n-1。
- 对于任何一棵非空的二叉树,如果叶节点个数为n0,度数为2的节点个数为n2,则有: n0 = n2 + 1。
4的证明:在一棵二叉树中,除了叶子结点(度为0)之外,就剩下度为2(n2)和1(n1)的结点了。则树的结点总数为T = n0+n1+n2;在二叉树中结点总数为T,而连线数为T-1.所以有:n0+n1+n2-1 = 2*n2 +n1;最后得到n0 = n2+1;
完全二叉树的性质:
- 具有n个结点的完全二叉树的深度为log2n+1.
证明: 满二叉树是完全二叉树,对于深度为k的满二叉树中结点数量是2k-1 = n,完全二叉树结点数量肯定最多2k-1,同时完全二叉树倒数第二层肯定是满的(倒数第一层有结点,那么倒是第二层序号和满二叉树相同),所以完全二叉树的结点数最少大于少一层的满二叉树,为2k-1-1。
根据上面推断得出: 2k-1-1< n=<2k-1,因为结点数Nn为整数那么n<=2k-1可以推出n<=2k ,n>2(k-1)-1可以推出 n>=2k-1,所以2k-1<n<=2k 。即可得k-1<=log2n<k 而k作为整数因此k=[log2n]+1。 - 如果有一颗有n个节点的完全二叉树的节点按层次序编号,对任一层的节点i(1<=i<=n)有
- 如果i=1,则节点是二叉树的根,无双亲,如果i>1,则其双亲节点为[i/2],向下取整
- 如果2i>n那么节点i没有左孩子,否则其左孩子为2i
- 如果2i+1>n那么节点没有右孩子,否则右孩子为2i+1
在上图中验证
第一条:
当i=1时,为根节点。当i>1时,比如结点为7,他的双亲就是7/2= 3;结点9双亲为4.
第二条:
结点6,6* 2 = 12>10,所以结点6无左孩子,是叶子结点。结点5,5*2 = 10,左孩子是10,结点4,为8.
第三条:
结点5,2*5+1>10,没有右孩子,结点4,则有右孩子。
二叉树可以用数组建立也可以用结构体建立。
数组建立二叉树://前序遍历方式建立二叉树
char s[MAXn]; //开辟数组用来模拟存储二叉树
void scan(int n) //n为节点下标 (从1开始)
{
char c;
cin>>c;
s[n]=c;
if(c!='#') //#表示空节点
{
scan(n*2); //左节点(上面提到了,左节点下坐标=其父节点的二倍
scan(n*2+1); //右节点
}
}
结构体建立二叉图:
struct node{
node *l; //左节点
node *r; //右节点
char c;
node()
{
l=r=