与线性表一样,二叉树也有顺序存储结构与链式存储结构
二叉树的顺序存储:
二叉树的顺序存储就是用一组地址连续的存储单元来存放二叉树的数据元素。
满二叉树或完全二叉树采用顺序存储结构比较合适,既能最大可能的节省存储空间,又可以利用数组的下标确定结点在二叉树的位置以及结点之间的关系。
对于一般的二叉树,如果需要增加很多空结点才能改造为完全二叉树的一般树非常不建议采用顺序存储结构,这样会造成空间的大量浪费。最坏情况:只有右支的右单支树(除叶子结点外每个结点只有一个右孩子的树),一颗高度为h的右单支树,只有h个结点,但需要分配个存储单元(其中个结点都为空),如图所示:
对于一般的二叉树:
孩子找双亲:
如果一个孩子结点的编号为i,则它的双亲结点为 [i // 2](保留整数部分)
双亲找孩子:
如果一个双亲结点的编号为i,则它的左孩子结点为 [2i],右孩子结点为 [2i+1]。
二叉树的链式存储:
二叉树的链式存储中,二叉树的每个结点由
lchild(左指针域,用于存储左孩子结点的地址)
data(值域,用于存储对应的数据元素)
rchild(右指针域,用于存储右孩子结点的地址)这三部分组成,这种存储结构称为二叉链(binary linked list)。二叉链中通过根结点指针b来唯一标识整个存储结构,称为二叉树b。
二叉链中结点类型声明如下:
typedef struct node {
DataType data;
struct node* lChild;
struct node* rChild;
}BTNode;
如图所示:
二叉链存储结构的优点:
对于一般的二叉树比较节省存储空间
访问一个结点的孩子结点很方便
但访问一个结点的双亲结点需要扫描所有结点。
二叉树的基本运算及其实现:
为了方便,我们采用二叉链来实现二叉树的基本运算。
1.二叉树的高度
| 1 t->lchild==NULL&&t->rchild==NULL
H(t)=|
| MAX(H(t->lchild),H(t->rchild))+1 其他
2.二叉树的结点数
| 1 t->lchild==NULL&&t->rchild==NULL
C(t)=|
| C(t->lchild)+C(t->rchild)+1 其他
3.二叉树的叶子结点数
| 1 t->lchild==NULL&&t->rchild==NULL
C1(t)=|
| C1(t->lchild)+C1(t->rchild) 其他
二叉树的遍历
先序遍历:
1.访问根结点
2.先序遍历左子树
3.后续遍历右子树
中序遍历:
1.中序遍历左子树
2.访问根结点
3.中序遍历右子树
后序遍历:
1.后序遍历左子树
2.后序遍历右子树
3.访问根结点
层次遍历:
若二叉树非空,则按照从上到下、从左到右依次访问每个结点
二叉树的构造、二叉树的还原、二叉树的确定:
任何n个结点的二叉树,都可以它的
中序序列与先序序列
中序序列与层序序列
中序序列与后序序列
唯一确定。