树 (和图一样是非线性结构)
树的定义
专业定义:
1、有且只有一个称为根的节点
2、有若干互不相交的子树,这些子树本身也是一颗树
通俗定义:
1、树由节点和边组成
2、每一个节点只有一个父节点,但可由多个字节点
3、没父节点的是根节点
树的分类
1、一般树
2、二叉树:一般二叉树、满二叉树(满了,在不增加层次的条件下不能在多一个节点了)、完全二叉树(完全按照从上到下,从左到右的树)。
3、森林:N个互补相交的树的结合
树的存储
(1)连续存储:必须构造出完全二叉树(以数组来存储)
(2)链式存储:先序、中序、后序
(3)一般树的存储:双亲表示法、孩子表示法、双亲孩子表示法、
二叉树表示法:把普通树转换为二叉树,只要左指针域指向他的第一个孩子,右指针域指向他的兄弟,就可以实现转换。(树都可以实现转换,但构造的二叉树一定没有右子树)
(4)森林的存储:转换成二叉树来存储,可能有右子树
树的操作 (二叉树)##
1、树的遍历(把非线性的树转换成线性的序列)
(1)先序遍历(先根节点)
先访问根节点、在访问左子树、在访问右子树。
(2)中序遍历(中间访问根节点)
先访问左子树、再根节点,再右子树
(3)后序遍历(最后访问根节点)
先左子树,再右子树,再根节点
2、已知两种遍历序列求原始二叉树(根据根再中序中的位置,来判断左子数和右子树来还原)
(1)只有通过先序和中序,或中序和后序才能还原二叉树,通过先序和后序不能还原。
(2)通过先序和中序:通过先序首先判断根,根再中序中把树分为了左子树和右子树。
(3)通过中序和后序:从后序来判断哪个是根,即把后序倒着来
树的应用
树是数据库中数据组织一种重要的形式、操作系统父进程关系本身就是一颗树、面向对象中类的继承关系
二叉树链式存储算法
1、静态创建树
`
//定义一个节点的结构
class Tree{
public:
char data;
Tree* leftchild;
Tree* rightchild;
};
//创建树
Tree* pa=new Tree;
Tree* pb=new Tree;
Tree* pc=new Tree;
Tree* pd=new Tree;
pa->data='a';
pb->data='b';
pc->data='c';
pd->data='d';
pa->leftchild=pb;
pa->rightchild=pc;
pb->leftchild=pd;
pb->rightchild=NULL;
pd->leftchild=pd->rightchild=pc->leftchild=pc->rightchild=NULL;
return pa;//知道一颗树的根节点即可知道整个树,所有返回 根节点即可
`
2、遍历树
`
//先序遍历树
void pre_show(Tree* t)
{
if(t!=NULL)
{
cout<<t->data<<endl;
if(t->leftchild!=NULL)
{
pre_show(t->leftchild);
}
if(t->rightchild!=NULL)
{
pre_show(t->rightchild);
}
}
}
//中序遍历
void mid_show(Tree* t)
{
if(t!=NULL)
{
if(t->leftchild!=NULL)
{
mid_show(t->leftchild);
}
cout<<t->data<<endl;
if(t->rightchild!=NULL)
{
mid_show(t->rightchild);
}
}
}
//后序遍历
void last_show(Tree* t)
{
if(t!=NULL)
{
if(t->leftchild!=NULL)
{
last_show(t->leftchild);
}
if(t->rightchild!=NULL)
{
last_show(t->rightchild);
}
cout<<t->data<<endl;
}
}
`