1. 概念
1.1 二叉树的定义
二叉树( Binary Tree)是n(n≥0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成,且具有以下特点:
1.2 二叉树的特点
1)每个结点最多有两颗子树,结点度最大为二
2)左子树和右子树是有顺序的,次序不能颠倒
3)即使某结点只有一子树,也要区分左右子树
4)具有5种形态:空二叉树、只有一个根节点、根节点只有左子树、根节点只有右子树、根节点既有左子树也有右子树
1.3 特殊的二叉树
1)斜树:所有结点只有左子结点 或 只有右子结点
2)满二叉树:所有的分支结点都存在左子树和右子树,并且所有的叶子结点都在同一层上,这样就是满二叉树。就是完美圆满的意思,关键在于树的平衡
3)完全二叉树:对一棵具有n个结点的二叉树按层序排号,如果编号为i的结点与同样深度的满二叉树编号为i结点在二叉树中位置完全相同,就是完全二叉树。满二叉树必须是完全二叉树,反过来不一定成立。 【看着树的示意图,心中默默给每个结点按照满二二叉树的结构逐层顺序编号,如果编号出现空档,就说明不是完全二叉树,否则就是】
https://www.cnblogs.com/polly333/p/4740355.html
2. 二叉树的性质
2.1 一般二叉树性质
1)在二叉树的i层上,至多有2^i-1个节点(i>=1)
2)深度为K的二叉树上最多有2^k-1个结点(k>=1)
3)对于任何一棵二叉树T,如果叶节点个数为n0,度数为2的节点个数为n2,则有: n0 = n2 + 1
终端结点数其实就是叶子结点数,而一-棵二叉树,除了叶子结点外,剩下的就是度为1或2的结点数了,我们设n1为度是1的结点数。则树T结点总数n=no+n1+n2。
2.2 完全二叉树特有性质
1)具有n个结点的完全二叉树的深度为[log2 n]+1 ([x]表示不大于x的最大整数
2)如果有一颗有n个节点的完全二叉树的节点按层次序编号,对任一层的节点i(1<=i<=n)有:
1.如果i=1,则节点是二叉树的根,无双亲,如果i>1,则其双亲节点为[i/2],向下取整
2.如果2i>n那么节点i没有左孩子,否则其左孩子为2i
3.如果2i+1>n那么节点没有右孩子,否则右孩子为2i+1
3. 二叉树的存储结构
3.1 顺序存储
1)由于二叉树的特殊性,使用顺序结构也可以实现。但又对于另一些特殊二叉树,这种方式又有点浪费空间
3.2 链式二叉树
1)指针域 以及两个孩子域
#define MAXSIZE 100
typedef int ElemType;
struct BiTree{
ElemType data; //数据域
BiTree *leftchild; //左指针域
BiTree *rightchild; //右指针域
};
4. 二叉树的遍历
4.1 遍历分类及其原理
二叉树的遍历( traversing binary tree )是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。
1)前序遍历:若二又树为空,则返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树【根-左-右】
2)中序遍历:若二又树为空,则返回,否则先中序遍历左子树,然后访问根结点,再中序遍历右子树【左-根-右】
3)后序遍历:若二又树为空,则返回,否则先后序遍历左子树,然后后序遍历右子树,再访问根【左-右-根】
4)层序遍历:自根结点开始,自上而下,逐层遍历
1、已知前序遍历序列和中序遍历序列, 可以唯一确定1棵二叉树
2、已知后序遍历序列和中序遍历序列, 可以唯一确定1棵二叉树
4.2 遍历二叉树的实现
#define MAXSIZE 100
typedef int ElemType;
struct BiTree{
ElemType data; //数据域
BiTree *leftchild; //左指针域
BiTree *rightchild; //右指针域
};
typedef BiTree *BiTreeptr;
//二叉树前序遍历
void PreoderBiTree(BiTreeptr t)
{
if (t == NULL)
return;
printf("%d ", (t->data));
PreoderBiTree(t->leftchild); // 遍历左树
PreoderBiTree(t->rightchild); // 遍历右树
}
//二叉树中序遍历
void InoderBiTree(BiTreeptr t)
{
if (t == NULL)
return;
InoderBiTree(t->leftchild); // 遍历左树
printf("%d ", (t->data));
InoderBiTree(t->rightchild); // 遍历右树
}
//二叉树后序遍历
void PostoderBiTree(BiTreeptr t)
{
if (t == NULL)
return;
PostoderBiTree(t->leftchild); // 遍历左树
PostoderBiTree(t->rightchild); // 遍历右树
printf("%d ", (t->data));
}
5. 二叉树的建立
1)那么我们如何在内存中生长一棵二叉链表的二叉树呢? 需要进行扩展
//以前序遍历方式生成二叉链的二叉树
void CreateBiTree(BiTreeptr *t)
{
char ch;
cin >> ch; //ch存储的是字符的ASCII码,以整形存储
cout << ch << endl;
if (ch == '#')
*t = NULL;
else
{
*t = new BiTree;
if (!*t)
exit(OVERFLOW);
(*t)->data = ch; //生成根节点
CreateBiTree(&(*t)->leftchild); //构造左子树
CreateBiTree(&(*t)->rightchild); //构造右子树
}
}