二叉树是结点的有限集合,这个有限集合或者为空集(称为空二叉树),或者由一个根结点及两棵不相交的、分别称为这个根的左子树和右子树的二叉树组成。
图5.12所示的是一棵二叉树,根结点为A,其左子树包含结点B、D、G,右子树包含结点C、E、F、H、I。根A的左子树又是一棵二叉树,其根结点为B,有非空的左子树(由结点D、G组成)和空的右子树。根A的右子树也是一棵二叉树,其根结点为C,有非空的左子树(由结点E、H、I组成)和右子树(由结点F组成)。
上面介绍的树的基本术语在二叉树中同样适用,但需要说明的是,尽管树和二叉树的概念之间有许多关系,但它们是两个概念。二叉树不是树的特殊情况,树和二叉树之间最主要的区别是:二叉树是有序的,二叉树的结点的子树要区分左子树和右子树,即使在结点只有一棵子树的情况下也要明确指出该子树是左子树还是右子树。例如,图5.13中是四棵不同的二叉树,但如果作为树,它们就是相同的了。
图5.12二叉树
在树与二叉树之间有一个自然的一一对应的关系,每一棵树都能惟一地转换成它所对应的二叉树。把树转换成对应的二叉树的方法是:将树中所有相邻兄弟用线连起来,然后去掉双亲到子女的连线,只留下双亲到第一个子女的连线。对图5.11所示的树用上述方式处理后稍加倾斜,就得到对应的二叉树,
如图5.14所示。
图5.13四棵不同的二叉树
满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶结点都在同一层上,这样的一棵二叉树称为满二叉树。
完全二叉树:一棵深度为k的有 n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。显然,一棵满二叉树必定是一棵完全二叉树。
在图5.15中,图(a)为一棵满二叉树,图(b)为一棵完全二叉树,图(c)为一棵非完全二叉树。
图5.14树对应的二叉树
图5.15满二叉树、完全二叉树和非完全二叉树
1)先序遍历
void PreOrder(BiTree root)
{ if (root!=NULL)
{
Visit(root ->data);
PreOrder(root ->LChild);
PreOrder(root ->RChild);
}
}
算法 6.1 先序遍历二叉树
2)中序遍历
void InOrder(BiTree root)
{ if (root!=NULL)
{
InOrder(root ->LChild);
Visit(root ->data);
InOrder(root ->RChild);
}
}
算法 6.2 中序遍历二叉树
3)后序遍历
void PostOrder(BiTree root)
{ if(root!=NULL)
{
PostOrder(root ->LChild);
PostOrder(root ->RChild);
}
}
先、中、后序遍历二叉树的非递归算法
1.先序遍历非递归算法
#define maxsize 100
typedef struct
{
Bitree Elem[maxsize];
int top;
}SqStack;
void PreOrderUnrec(Bitree t)
{
SqStack s;
StackInit(s);
p=t;
while (p!=null || !StackEmpty(s))
{
while (p!=null) //遍历左子树
{
visite(p->data);
push(s,p);
p=p->lchild;
}//endwhile
if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历
{
p=pop(s);
p=p->rchild;
}//endif
}//endwhile
}//PreOrderUnrec
2.中序遍历非递归算法
#define maxsize 100
typedef struct
{
Bitree Elem[maxsize];
int top;
}SqStack;
void InOrderUnrec(Bitree t)
{
SqStack s;
StackInit(s);
p=t;
while (p!=null || !StackEmpty(s))
{
while (p!=null) //遍历左子树
{
push(s,p);
p=p->lchild;
}//endwhile
if (!StackEmpty(s))
{
p=pop(s);
visite(p->data); //访问根结点
p=p->rchild; //通过下一次循环实现右子树遍历
}//endif
}//endwhile
}//InOrderUnrec
3.后序遍历非递归算法
#define maxsize 100
typedef enum{L,R} tagtype;
typedef struct
{
Bitree ptr;
tagtype tag;
}stacknode;
typedef struct
{
stacknode Elem[maxsize];
int top;
}SqStack;
void PostOrderUnrec(Bitree t)
{
SqStack s;
stacknode x;
StackInit(s);
p=t;
do
{
while (p!=null) //遍历左子树
{
x.ptr = p;
x.tag = L; //标记为左子树
push(s,x);
p=p->lchild;
}
while (!StackEmpty(s) && s.Elem[s.top].tag==R)
{
x = pop(s);
p = x.ptr;
visite(p->data); //tag为R,表示右子树访问完毕,故访问根结点
}
if (!StackEmpty(s))
{
s.Elem[s.top].tag =R; //遍历右子树
p=s.Elem[s.top].ptr->rchild;
}
}while (!StackEmpty(s));
}//PostOrderUnrec