第六章 树和二叉树
一 树
定义
树是由根结点和若干颗子树构成的。树是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的结点,所定义的关系称为父子关系。父子关系在树的结点之间建立了一个层次结构。在这种层次结构中有一个结点具有特殊的地位,这个结点称为该树的根结点,或称为树根。
单个结点是一棵树,树根就是该结点本身。
二 二叉树
定义
二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
三 实践
编写下面的函数
a.建立一棵二叉树
b.实现二叉树的三种递归的遍历
c.实现二叉树的先根,中根非递归遍历
d.求二叉树叶子结点的个数
e.求二叉树的深度
f.按层遍历二叉树
#define STACKSIZE 100
#define JIA_STACKSIZE 10
#define size 20
typedef int Status;
typedef struct treenode //定义二叉树
{
char data;
struct treenode *lchild,*rchild;
}treenode,*treelink;
typedef treelink SElemtype;
typedef struct stack //定义栈
{
SElemtype *top,*base;
int stacksize;
}SStack;
typedef struct //定义队(循环队列)
{
int front;
int rear;
SElemtype elem[size];
}SqQueue;
int main()
{
treelink t=NULL;
printf("请输入二叉树:");
creatree(t);
printf("请输出二叉树(前序遍历(递归)):");
preorde(t);
printf("\n请输出二叉树(中序遍历(递归)):");
zhpreorde(t);
printf("\n请输出二叉树(后序遍历(递归)):");
hopreorde(t);
printf("\n请输出二叉树(前序遍历(非递归)):");
nopreorde(t);
printf("\n请输出二叉树(中序遍历(非递归)):");
nozhpreorde(t);
printf("\n请输出二叉树(按层遍历二叉树):");
cepreorde(t);
printf("\n请输出二叉树叶子结点的个数:%d",leafcount(t));
printf("\n请输出二叉树的深度:%d",depth(t));
return 0;
}
//初始化栈
Status InitStack(SStack &S)
{
S.base=(SElemtype *)malloc(STACKSIZE*sizeof(SElemtype));
if(!S.base) return 0;
S.top=S.base;
S.stacksize=STACKSIZE;
return 1;
}
//进栈(插入)
Status Push(SStack &S,SElemtype e)
{
if(S.top-S.base>=S.stacksize)
{
S.base=(SElemtype*)realloc(S.base,(S.stacksize+JIA_STACKSIZE)*sizeof(SElemtype));
if(!S.base) return 0;
S.top=S.base+S.stacksize;
S.stacksize+=JIA_STACKSIZE;
}
*S.top=e;
S.top++;
return 1;
}
//取栈顶元素
Status Getop(SStack S,SElemtype &e)
{
if(S.top==S.base) return 0;
e=*(S.top-1);
return 1;
}
//出栈(删除)
Status Pop(SStack &S, SElemtype &e)
{
if(S.top==S.base) return 0;
S.top--;
e=*S.top;
return 1;
}
Status initQueue(SqQueue &Q) //初始化循环队列
{
Q.front=Q.rear=0;
return 1;
}
Status enQueue(SqQueue &Q,SElemtype e) //进队
{
if((Q.rear+1)%size==Q.front)
return 0;
Q.elem[Q.rear]=e;
Q.rear=(Q.rear+1)%size;
return 1;
}
Status deQueue(SqQueue &Q,SElemtype &e) //出队
{
if(Q.front==Q.rear)
return 0;
e=Q.elem[Q.front];
Q.front=(Q.front+1)%size;
return 1;
}
int creatree(treelink &T)//生成二叉树
{
char ch;
ch=getchar();
if(ch=='#')
T=NULL;
else
{
T=(treelink)malloc(sizeof(treenode));
if(!T) return 0;
T->data=ch;
creatree(T->lchild); //构造左子树
creatree(T->rchild); //构造右子数
}
return 1;
}
void visit(treelink P)//查看
{
printf("%c ",P->data);
}
void preorde(treelink S)//前序遍历(递归)
{
if(S)
{
visit(S);
preorde(S->lchild);
preorde(S->rchild);
}
}
Status nopreorde(treelink S)//前序遍历(非递归)
{
SStack T;
treelink p;
InitStack(T);
p=S;
while(p||!(T.top==T.base))
{
if(p)
{
visit(p);
Push(T,p);
p=p->lchild;
}
else
{
Pop(T,p);
p=p->rchild;
}
}
return 1;
}
void zhpreorde(treelink S)//中序遍历(递归)
{
if(S)
{
zhpreorde(S->lchild);
visit(S);
zhpreorde(S->rchild);
}
}
Status nozhpreorde(treelink S)//中序遍历(非递归)
{
SStack T;
treelink p;
InitStack(T);
p=S;
while(p||!(T.top==T.base))
{
if(p)
{
Push(T,p);
p=p->lchild;
}
else
{
Pop(T,p);
visit(p);
p=p->rchild;
}
}
return 1;
}
void hopreorde(treelink S)//后序遍历(递归)
{
if(S)
{
hopreorde(S->lchild);
hopreorde(S->rchild);
visit(S);
}
}
Status leafcount(treelink T)//求叶子结点的个数
{
SStack S;
treelink p;
InitStack(S);
p=T;
int count=0;
while(p||!(S.top==S.base))
{
if(p)
{
if(p->lchild==NULL&&p->rchild==NULL)//左右孩子都为空
count++; //计数+1
Push(S,p); //进栈
p=p->lchild; //遍历左子树
}
else
{
Pop(S,p); //出栈
p=p->rchild; //遍历右子树
}
}
return count;
}
Status depth(treelink T)//二叉树的深度
{
int m,n;
if(T==NULL)
return 0;
else
{
m=depth(T->lchild); //递归左子树
n=depth(T->rchild); //递归右子树
return m>=n?m+1:n+1; //输出m和n中最大的+1
}
}
void cepreorde(treelink T)//按层遍历二叉树
{
SqQueue S;//定义队
treelink p;
initQueue(S);//初始化队
p=T;
if(p)
enQueue(S,p);//进队
while(!(S.front==S.rear)) //队不空
{
deQueue(S,p);
visit(p);
if(p->lchild)
{
enQueue(S,p->lchild);//进队
}
if(p->rchild)
{
enQueue(S,p->rchild);//进队
}
}
}