二叉树的逻辑结构和遍历
二叉树的顺序存储:
前提: 是完全二叉树
问题: 用一块连续的存储单元(数组)存储节点元素,怎么才能体现树的逻辑结构呢(怎么体现1是23的双亲节点,23是1的孩子节点)?
答: 利用了完全二叉树的性质,可以通过数组下标找到某个节点的双亲节点或孩子节点。(2节点的孩子节点是数组下标为4和5的节点)
问题: 非完全二叉树怎么实现顺序存储呢?
答: 将非完全二叉树补成完全二叉树即可,将补上去的节点数组对应位置置0。
二叉树的顺序存储的缺点:
会浪费大量的存储空间,这种存储方式比较适合完全二叉树
二叉树的链式存储(常):
问题: 空指针域与非空指针域的关系
二叉树链式的代码定义:
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
二叉树的遍历方法:
先序遍历:
递归实现:
void PreOrder(BiTree T){
if(T != NULL){
visit(T);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
栈的实现:
中序遍历:
递归实现:
void InOrder(BiTree T){
if(T != NULL){
PreOrder(T->lchild);
visit(T);
PreOrder(T->rchild);
}
}
栈的实现:
//初始时依次扫描根节点的所有左侧节点并入栈
//出栈一个节点,访问该节点
//扫描该节点的右孩子节点并入栈
//依次扫描右孩子节点的所有左侧节点并入栈
//反复该过程直到栈空为止
void InOrder(BiTree T){
InitStack(S);
BiTree p = T;
while(p != NULL || IsEmpty(S)){
if(p != NULL){
Push(S,p);
p = p->lchild;
}
else{
Pop(S,p);
visit(p);
p = p->rchild;
}
}
}
后序遍历:
递归实现:
void PostOrder(BiTree T){
if(T != NULL){
PreOrder(T->lchild);
PreOrder(T->rchild);
visit(T);
}
}
层次遍历:
//初始时将根入队并访问根节点,然后出队
//若有左子树,则将左子树的根入队
//若有右子树,则将右子树的根入队
//然后出队,访问该节点
//反复该过程直到队列空为止
void LevelOrder(BiTree T){
InitQueue(Q);
BiTree p;
EnQueue(Q,T);
while(!isEmpty(Q)){
DeQueue(Q,p);
visit(p);
if(p->lchild != NULL)
EnQueue(Q,p->lchild);
if(p->rchild != NULL)
EnQueue(Q,p->rchild);
}
}
遍历序列转二叉树:
先序遍历序列+中序遍历序列:
后序遍历序列+中序遍历序列:
层次遍历序列+中序遍历序列:
ps: 后序遍历序列+前序遍历序列不能唯一确定一颗二叉树