四,二叉树的存储结构
1.顺序存储
二又树的顺序存储是用一片连续的存储空间来存放二叉树的所有结点及其之间的逻辑关系的。此时需要把二叉树的所有结点按某种顺序排列成一个适当的线性序列,并由结点之间的相对位置反映结点之间的逻辑关系。
由二叉树的性质5可知, 对于一棵完全二叉树,对结点按层序编号, 结点的序号蕴含结点之间的逻辑关系。因此,对于一棵完全二叉树,对结点按层序编号,就能得到一个这样的线性序列, 把所有结点按顺序存入一维数组的相应位置上,即编号为的结点存储在下标为的位置上(为方便操作, 结点从数组下标为1的单元开始存储),这样, 结点的位置(下标)就反映了结点之间的逻辑关系。
例如下图,下标为的结点如果有双亲,则其双亲的下标为i2:如果有左孩子,则其左孩子的下标为2i:如果有右孩子,则其右孩子的下标为2i+1,如图
#define MaxSize 30
typedef struct SeqBT{
char btree[MaxSize];
int length;//二叉树中所含结点的实际个数
}SeqBT;
比较适合完全二叉树,对于一般的,用链式较好
2.链式存储
由于二叉树的结点含有一个元素和两个分别指向其左、右子树的分支, 所以,在链式存储中,结点中不仅要含有结点本身的信息,还要含有左、右孩子的信息,即指向左、右孩子的指针。因此, 结点应至少含3个域: 一个数据域(data)、两个指针域(指向左孩子的指针域Ichild和指向右孩子的指针域rchild), 如图所示:
typedef struct BNode{
ElemType data;
struct BNode *lchild;
struct BNode *rchild;
}BNode;
typedef BTNode* BinTree;
BinTree root;
可以证明,在一颗含有n个结点的二叉树的二叉链表的2n个指针域中,有n+1个空链域。
========================================================================
五,二叉树的遍历
(1)先序遍历
若二叉树为空,则空操作,否则依次执行以下操作
先根结点,再遍历根结点的左子树,再遍历根结点的右子树
void PreOrder(BinTree root){
if(root!=NULL){
printf("%c",root->data);
printf(root->lchild);
printf(root->rchild);
}
}
=========================================================================
(2)中序遍历
从左往右依次遍历遍历结果为:CDBEAFG
若二叉树为空,则空操作,否则依次执行以下操作
先遍历根结点的左子树,再根结点,再遍历根结点的右子树
void InOrder(BinTree root){
if(root!=NULL){
InOrder(root->lchild);
printf("%c",root->data);
InOrder(root->rchild);
}
}
=======================================================================
(3)后序遍历
若二叉树为空,则空操作,否则依次执行以下操作
先遍历根结点的左子树,再遍历根结点的右子树,再根结点,
void PostOrder(BinTree root){
if(root!=NULL){
PostOrder(root->lchild);
PostOrder(root->rchild);
printf("%c",root->data);
}
}
注意,如果想确定二叉树的形状,两个遍历里必须要有终须中序遍历
(前中,后中,不可以前后)