存储结构
由于二叉树的特殊性,可以用顺序结构来实现二叉树。如果是完全二叉树,直接按照树的层序依次将每个结点存入数组,相应的下标对应其相同的位置。
如果是一般的二叉树,尽管层序编号不能反映逻辑关系,但是可以将其按完全二叉树编号,把不存在的结点设置为^
这时候,若情况比较极端:一颗深度为k的右斜树,其只有k个结点,却需要分配2^k -1个存储单元空间,比较浪费。所以一般顺序存储结构只用于完全二叉树。
e.g
顺序结构的普适性不强,考虑链式结构。二叉树每个结点最多有两个孩子,所以二叉链表是比较自然的想法。
lchild | data | rchild |
结构代码示例
typedef struct Bnode{
ElemType data;
struct Bnode *lch,*rch;
}Bnode,*Btree;
e.g
建立
要建立如上图所示的普通二叉树,自然而然我们需要知道结点的序列。对于二叉树的遍历有前中后三种遍历顺序,而且只有知道一棵树的“前序、中序”或者“中序、后序”才能唯一确定这棵树。
所以对于一颗普通二叉树,我们对其进行扩展。也就是将二叉树中每个结点的空指针引出一个“虚有的”结点,其值为特定,例如‘#’。一般称这种二叉树为原二叉树的扩展二叉树。对于扩展的二叉树,只要知道一种遍历的序列(前序或后序)即可确定一颗二叉树了。
图片中前序遍历的序列为AB#D##C##
代码示例(以已知扩展的前序序列为例)
#include<bits/stdc++.h>
using namespace std;
typedef struct Bnode{
char data;
Bnode *lch,*rch;
}Bnode,*Btree;
void CreatBtree(Btree &T)
{
char ch;
cin>>ch;
if(ch=='#') T=NULL;
else{
T=(Btree)malloc(sizeof(Bnode));
if(!T) exit(OVERFLOW);
T->data=ch;
CreatBtree(T->lch);
CreatBtree(T->rch);
}
}
void PreOrderTraverse(Btree T)
{
if(T==NULL) return ;
cout<<T->data<<' ';//可改为其他操作
PreOrderTraverse(T->lch);
PreOrderTraverse(T->rch);
}
void InOrderTraverse(Btree T)
{
if(T==NULL) return ;
InOrderTraverse(T->lch);
cout<<T->data<<' ';
InOrderTraverse(T->rch);
}
void PostOrderTraverse(Btree T)
{
if(T==NULL) return ;
PostOrderTraverse(T->lch);
PostOrderTraverse(T->rch);
cout<<T->data<<' ';
}
int main()//以已知扩展前序序列为例
{
cout<<"请输入扩展二叉树的扩展前序序列"<<endl;
Btree root;
CreatBtree(root);
cout<<endl;
cout<<"树的前序为:"<<endl;
PreOrderTraverse(root);
cout<<endl;
cout<<"树的中序为:"<<endl;
InOrderTraverse(root);
cout<<endl;
cout<<"树的后序为:"<<endl;
PostOrderTraverse(root);
cout<<endl;
}