一、二叉树的性质
- 二叉树的第i层上最多有2i-1个结点(i≥1)。
- 深度为k的二叉树最多有2k-1个结点(k≥1 )
- 一棵非空二叉树,若叶子结点数为n0,度数为2的结点数为n2,则n0=n2+1。
1.1 完全二叉树特有性质
- 具有n个结点的完全二叉树的深度必为log2n+1
- 对于具有n个结点的完全二叉树,如果按照从上到下和从左到右的顺序对二叉树中的所有结点从1开始顺序编号,则对于任意的序号为i的结点有如下性质:
- 对于具有n个结点的完全二叉树,如果按照从上到下和从左到右的顺序对二叉树中的所有结点从1开始顺序编号,则对于任意的序号为i的结点有如下性质:
(1)如i=1,则序号为i的结点是根结点,无双亲结点;如i>1,则序号为i的结点的双亲结点序号为i/2
(2)如2i>n,则序号为i的结点无左孩子;如2i≤n,则序号为i的结点的左孩子结点的序号为2i
(3)如2i+1>n,则序号为i的结点无右孩子;如2i+1≤n,则序号为i的结点的右孩子结点的序号为2i+1
1.2满二叉树特殊性质
- 深度为k时,结点数n=2k-1
- 不存在度为1的结点
- 每个结点都有两棵高度相同的子树
- 深度为k的完全二叉树,前k-1层构成一棵深度为k-1的满二叉树
二、二叉树的存储
2.1顺序存储
不常用,局限性比较大,不写了。
2.2链式存储
链表中每个结点由 三个区域组成:
名称 | 意义 |
---|---|
data | 数据:存放节点的数据信息 |
lchild | 存放指向左孩子的指针 |
rchild | 存放指向右孩子的指针 |
结点数据类型定义:
typedef struct BiTNode{
DataType data;
structBiTNode *lchild, *rchild;
} BiTNode, *BiTree;
说明: 在n个结点的二叉链表中,有n+1个空指针域。 1
2.3二叉树的遍历
2.3.1 遍历的方法
- 先序:DLR
- 中序:LDR
- 后序:LRD
- 层序遍历:按二叉树的层序编号的次序访问各结点。
树:二叉树的层序遍历算法(超简洁实现及详细分析)
先序:
若二叉树为空,则遍历结束,否则依次执行如下3个操作:
1.访问根结点
2.先序遍历根结点的左子树
3.先序遍历根结点的右子树
void PreOrder(BiTreebt)
/*先序遍历二叉树, bt为指向二叉树(或某一子树)根结点的指针*/
{
if (bt==NULL)
return ;
Visit(bt->data); /*访问根结点*/
PreOrder(bt->lchild); /*先序遍历左子树*/
PreOrder(bt->rchild); /*先序遍历右子树*/
}
中序:
若二叉树为空,则遍历结束,否则依次执行如下3个操作:
1.中序遍历根结点的左子树
2.访问根结点
3.中序遍历根结点的右子树
void InOrder(BiTreebt)
/*中序遍历二叉树, bt为指向二叉树(或某一子树)根结点的指针*/
{
if (bt=NULL)
return ;
InOrder(bt->lchild); /*中序遍历左子树*/
Visit(bt->data); /*访问根结点*/
InOrder(bt->rchild); /*中序遍历右子树*/
}
后序:
若二叉树为空,则遍历结束,否则依次执行如下3个操作:
1.后序遍历根结点左子树
2.后序遍历根结点右子树
3.访问根结点
void PostOrder(BiTreebt)
/*后序遍历二叉树, bt为指向二叉树(或某一子树)根结点的指针*/
{
if (bt=NULL)
return ;
Post Order (bt->lchild); /*后序遍历左子树*/
PostOrder(bt->rchild); /*后序遍历右子树*/
Visit(bt->data); /*访问根结点*/
}
小结
已知一棵二叉树的先序序列和中序序列,构造该二叉树的过程如下:
- 根据先序序列的第一个元素建立根结点;
- 在中序序列中找到该元素,确定根结点的左右子树的中序序列;.
- 在先序序列中确定左右子树的先序序列;
- 由左子树的先序序列和中序序列建立左子树;
- 由右子树的先序序列和中序序列建立右子树。
上机实验报告代码:
先序建立二叉树,后序打印;
#include "stdio.h" //设数据域类型为字符型
typedef struct node{
char data;
struct node *lchild,*rchild;
}BiTNode, *BiTree; //指向二叉树结点的指针类型
void CreateBiTree(BiTree *t); //构造二叉链表
void PostOrder(BiTree p); //后序遍历
void main( ) //主函数
{
BiTree T;
char ch1,ch2;
printf("\n请选择:\n");
ch1='y';
while(ch1=='y'||ch1=='Y')
{
printf("\n1------------------二叉树建立-------------");
printf("\n2------------------后序遍历---------------");
printf("\n3------------------退出-------------------\n");
scanf("\n%c",&ch2);
switch(ch2)
{
case '1':printf("请按先序输入建立二叉树存储的结点序列:\n");
CreateBiTree(&T);
break;
case '2':printf("该二叉树的后序遍历序列为:\n"); //调用后序遍历函数
PostOrder(T);
break;
case '3':printf("Thank you.\n");
ch1 = 'n';
break;
default: printf("输入有误,请重新选择");
}
}
}
void CreateBiTree( BiTree *t) //构造二叉链表
{
char ch;
scanf("\n%c",&ch);
if(ch=='0') *t=NULL; //读入0时,将相应结点置空
else
{
*t=new BiTNode; //生成结点空间
(*t)->data=ch;
CreateBiTree(&(*t)->lchild); //构造二叉树的左子树
CreateBiTree(&(*t)->rchild); //构造二叉树的右子树
}
}
void PostOrder(BiTree p) //后序遍历
{
if(p != NULL)
{
PostOrder(p->lchild);
PostOrder(p->rchild);
printf(" %c",p->data);
}
}
全部的结点为2n,其中被占用n-1,所以2n-(n-1)=n+1; ↩︎