1,问题一:给定一棵二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一次将单独输出一行),每一层要求访问的顺序为从左到右,并将结点依次编号。
解法一:基本思想:用层序遍历的方法,初始化一个队列,当每一层结点进队时,统计当前层的下一层结点数目,当结点出队时,统计出队次数是不是和上一层结点数目相等,若相等,则表明上一层的结点输出完毕,换行;否则不换行打印,继续统计当前层的下一层结点数目,直到队列为空。
代码如下:
#include "stdafx.h"
#include<stdio.h>
#include<malloc.h>
#define STACK_INCREMENT 10
#define STACK_INIT_SIZE 100
#define MAXSIZE 50
//char*ch="ABC D EFH I G ";
//char*ch="AB CD E ";
//char*ch="-+a *b -c d /e f ";
char*ch="124 57 8 3 6 ";
//二叉排序树的链式存储结构
typedef struct BiTNode
{
char data;
int count;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//队列的链式存储结构
typedef struct QNode
{
BiTree data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
//栈的顺序存储结构
typedef struct
{
BiTree *base;
BiTree *top;
int stacksize;
}Sqstack;
//初始化一个队列,用于二叉树的层次遍历
bool InitQueue(LinkQueue&Q)
{
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front )
exit(OVERFLOW);
Q.front ->next =NULL;
return true;
}
//初始化一个栈,用于二叉树的遍历
void InitStack(Sqstack&S)
{
S.base=(BiTree*)malloc(STACK_INIT_SIZE*sizeof(BiTNode));
if(!S.base)
exit(0);
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
}
bool EnQueue(LinkQueue&Q,BiTree T)
{
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));
if(!p)
return false;
p->data =T;
p->next =NULL;
Q.rear->next =p;
Q.rear=p;
return true;
}
bool DeleteQueue(LinkQueue&Q,BiTree &e)
{
QueuePtr q;
if(Q.front ==Q.rear )
return false;
q=Q.front->next ;
e=q->data;
Q.front->next=q->next ;
if(q==Q.rear )
Q.rear=Q.front ;
free(q);
return true;
}
//采用先序递归遍历创建一个二叉树
void CreateBiTree(BiTree&T)
{
//static int n=0;//用静态变量保存上次运算结果的值。
//char ch;
//static char *ch="ABCD E F ";
//ch=ch+n;
//scanf("%c",&ch);
if(*ch==' ')
{
T=NULL;
ch++;
//n++;
return;
}
else
{
if(!(T=(BiTNode*)malloc(sizeof(BiTNode))))
exit(OVERFLOW);
T->data=*ch++;
T->count =0;
//n++;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
//二叉树的分层遍历算法
void LevelTraverse(BiTree T)
{
int level[20];
int i,j;//i表示当前层的结点数目,j表示当前层的下一层节点数目。
int deCount;//用于记录某一层的出队次数,也就是改层的结点数。
LinkQueue Q;
InitQueue(Q);
BiTree p;
if(T)
{
EnQueue(Q,T);//根结点入队
i=j=0;//初始时,为第一层
j++;//第二层
deCount=0;//初始时,出队次数。
level[0]=1;//初始时,第一层的结点数目
level[1]=0;//初始时,第二层的结点数目
}
//一次循环,完成的任务是:队头结点出队并打印;统计当前层的出队次数;累计当前层的下一层的结点数目;
while(Q.front!=Q.rear )
{
DeleteQueue(Q,p);//出队
deCount++;//出队次数加1,当前层的结点数。
if(p->lchild )//如果当前结点的左孩子存在,下一层结点数加1
{
EnQueue(Q,p->lchild);
level[j]++;//统计下一层结点数目
}
if(p->rchild )//如果当前结点的右孩子存在,下一层结点数加1
{
EnQueue(Q,p->rchild);
level[j]++;//统计下一层结点数目
}
if(deCount!=level[i])//如果当前的出队次数不等于上一层的结点数目,不换行输出
{
printf("%c ",p->data);
}
else
{
printf("%c\n",p->data);//如果当前层的出队次数等于上一层的结点数目,换行输出,
deCount=0; //当前层输出完毕,同时下一层统计结点数的过程也完毕,并初始化下下一层统计结点数目的参数。
i=j;
j++;
level[j]=0; //当前层的下一层的初始结点数目。
}
}
printf("\n");
}
void main()
{
int length;
BiTree BST;
printf("*************************************************\n");
printf(" 二叉树按层次遍历算法 \n");
printf("*************************************************\n");
printf("输入的待建二叉树序列为:");
printf("%s",ch);
printf("\n");
CreateBiTree(BST);
printf("\n");
printf("输出按层次遍历结果:\n");
LevelTraverse(BST);
printf("\n");
free(BST);
}
运行结果如下:
2,问题二,打印二叉树中某层次的结点(从左至右),其中根结点为第1层。
再上一个问题的基础上,用一个判断语句:如果当前层等于要打印层,则输出,否则不输出
注意:上一题中,else语句中打印的是某一层的最后一个结点,再换行的,所以,else中也要有个判断句,否则某一层中的最后一个结点无法输出。
代码如下:
#include "stdafx.h"
#include<stdio.h>
#include<malloc.h>
#define STACK_INCREMENT 10
#define STACK_INIT_SIZE 100
#define MAXSIZE 50
//char*ch="ABC D EFH I G ";
//char*ch="AB CD E ";
char*ch="-+a *b -c d /e f ";
//char*ch="124 57 8 3 6 ";
//二叉排序树的链式存储结构
typedef struct BiTNode
{
char data;
int count;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//队列的链式存储结构
typedef struct QNode
{
BiTree data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
//栈的顺序存储结构
typedef struct
{
BiTree *base;
BiTree *top;
int stacksize;
}Sqstack;
//初始化一个队列,用于二叉树的层次遍历
bool InitQueue(LinkQueue&Q)
{
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front )
return false;
Q.front ->next =NULL;
return true;
}
//初始化一个栈,用于二叉树的遍历
void InitStack(Sqstack&S)
{
S.base=(BiTree*)malloc(STACK_INIT_SIZE*sizeof(BiTNode));
if(!S.base)
return ;
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
}
bool EnQueue(LinkQueue&Q,BiTree T)
{
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));
if(!p)
return false;
p->data =T;
p->next =NULL;
Q.rear->next =p;
Q.rear=p;
return true;
}
bool DeleteQueue(LinkQueue&Q,BiTree &e)
{
QueuePtr q;
if(Q.front ==Q.rear )
return false;
q=Q.front->next ;
e=q->data;
Q.front->next=q->next ;
if(q==Q.rear )
Q.rear=Q.front ;
free(q);
return true;
}
//采用先序递归遍历创建一个二叉树
void CreateBiTree(BiTree&T)
{
//static int n=0;//用静态变量保存上次运算结果的值。
//char ch;
//static char *ch="ABCD E F ";
//ch=ch+n;
//scanf("%c",&ch);
if(*ch==' ')
{
T=NULL;
ch++;
//n++;
return;
}
else
{
if(!(T=(BiTNode*)malloc(sizeof(BiTNode))))
return;
T->data=*ch++;
T->count =0;
//n++;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
//计算二叉树的深度
int depth(BiTree T)
{
int d1,d2;
if(!T)
return 0;
else
{
d1=depth(T->lchild);
d2=depth(T->rchild);
return (d1>d2)?(d1+1):(d2+1);
}
}
//二叉树的分层遍历算法
void LevelTraverse(BiTree T,int levels)
{
int level[20];
int i,j;//i表示当前层的结点数目,j表示当前层的下一层节点数目。
int deCount;//用于记录某一层的出队次数,也就是改层的结点数。
LinkQueue Q;
InitQueue(Q);
BiTree p;
if(T)
{
EnQueue(Q,T);//根结点入队
i=j=0;//初始时,为第一层
j++;//第二层
deCount=0;//初始时,出队次数。
level[0]=1;//初始时,第一层的结点数目
level[1]=0;//初始时,第二层的结点数目
}
//一次循环,完成的任务是:队头结点出队并打印;统计当前层的出队次数;累计当前层的下一层的结点数目;
while(Q.front!=Q.rear )
{
DeleteQueue(Q,p);//出队
deCount++;//出队次数加1,当前层的结点数。
if(p->lchild )//如果当前结点的左孩子存在,下一层结点数加1
{
EnQueue(Q,p->lchild);
level[j]++;//统计下一层结点数目
}
if(p->rchild )//如果当前结点的右孩子存在,下一层结点数加1
{
EnQueue(Q,p->rchild);
level[j]++;//统计下一层结点数目
}
if(deCount!=level[i])//如果当前的出队次数不等于上一层的结点数目,不换行输出
{
if(i==levels)
printf("%c ",p->data);
}
else
{
if(i==levels)
printf("%c",p->data);//如果当前层的出队次数等于上一层的结点数目,换行输出,
deCount=0; //当前层输出完毕,同时下一层统计结点数的过程也完毕,并初始化下下一层统计结点数目的参数。
i=j;
j++;
level[j]=0; //当前层的下一层的初始结点数目。
}
}
printf("\n");
}
void main()
{
int level;
int length;
BiTree BST;
printf("*************************************************\n");
printf(" 输出二叉树第n层结点的算法 \n");
printf("*************************************************\n");
printf("输入的待建二叉树序列为:");
printf("%s",ch);
printf("\n");
CreateBiTree(BST);
printf("\n");
length=depth(BST);
printf("输出此二叉树的深度为:%d\n",length);
printf("\n");
printf("请输入二叉树的level层(level<=%d,输出的为二叉树的第level+1层结点):",length);
scanf("%d",&level);
printf("\n");
printf("输出二叉树第%d层的结点:\n",level+1);
LevelTraverse(BST,level);
printf("\n");
free(BST);
}
运行结果如下:
3,问题三,输出二叉树某一层结点的数目。
代码如下:
#include "stdafx.h"
#include<stdio.h>
#include<malloc.h>
#define STACK_INCREMENT 10
#define STACK_INIT_SIZE 100
#define MAXSIZE 50
//char*ch="ABC D EFH I G ";
//char*ch="AB CD E ";
char*ch="-+a *b -c d /e f ";
//char*ch="124 57 8 3 6 ";
//二叉排序树的链式存储结构
typedef struct BiTNode
{
char data;
int count;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//队列的链式存储结构
typedef struct QNode
{
BiTree data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
//栈的顺序存储结构
typedef struct
{
BiTree *base;
BiTree *top;
int stacksize;
}Sqstack;
//初始化一个队列,用于二叉树的层次遍历
bool InitQueue(LinkQueue&Q)
{
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front )
return false;
Q.front ->next =NULL;
return true;
}
//初始化一个栈,用于二叉树的遍历
void InitStack(Sqstack&S)
{
S.base=(BiTree*)malloc(STACK_INIT_SIZE*sizeof(BiTNode));
if(!S.base)
return ;
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
}
bool EnQueue(LinkQueue&Q,BiTree T)
{
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));
if(!p)
return false;
p->data =T;
p->next =NULL;
Q.rear->next =p;
Q.rear=p;
return true;
}
bool DeleteQueue(LinkQueue&Q,BiTree &e)
{
QueuePtr q;
if(Q.front ==Q.rear )
return false;
q=Q.front->next ;
e=q->data;
Q.front->next=q->next ;
if(q==Q.rear )
Q.rear=Q.front ;
free(q);
return true;
}
//采用先序递归遍历创建一个二叉树
void CreateBiTree(BiTree&T)
{
//static int n=0;//用静态变量保存上次运算结果的值。
//char ch;
//static char *ch="ABCD E F ";
//ch=ch+n;
//scanf("%c",&ch);
if(*ch==' ')
{
T=NULL;
ch++;
//n++;
return;
}
else
{
if(!(T=(BiTNode*)malloc(sizeof(BiTNode))))
return;
T->data=*ch++;
T->count =0;
//n++;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
//计算二叉树的深度
int depth(BiTree T)
{
int d1,d2;
if(!T)
return 0;
else
{
d1=depth(T->lchild);
d2=depth(T->rchild);
return (d1>d2)?(d1+1):(d2+1);
}
}
//二叉树的分层遍历算法
void LevelTraverse(BiTree T,int levels)
{
int level[20];
int i,j;//i表示当前层的结点数目,j表示当前层的下一层节点数目。
int deCount;//用于记录某一层的出队次数,也就是改层的结点数。
LinkQueue Q;
InitQueue(Q);
BiTree p;
if(T)
{
EnQueue(Q,T);//根结点入队
i=j=0;//初始时,为第一层
j++;//第二层
deCount=0;//初始时,出队次数。
level[0]=1;//初始时,第一层的结点数目
level[1]=0;//初始时,第二层的结点数目
}
//一次循环,完成的任务是:队头结点出队并打印;统计当前层的出队次数;累计当前层的下一层的结点数目;
while(Q.front!=Q.rear )
{
DeleteQueue(Q,p);//出队
deCount++;//出队次数加1,当前层的结点数。
if(p->lchild )//如果当前结点的左孩子存在,下一层结点数加1
{
EnQueue(Q,p->lchild);
level[j]++;//统计下一层结点数目
}
if(p->rchild )//如果当前结点的右孩子存在,下一层结点数加1
{
EnQueue(Q,p->rchild);
level[j]++;//统计下一层结点数目
}
if(deCount==level[i])
{
if(i==levels)//如果等于输入的层数,则输出该层结点数目
printf("%d",level[i]);
deCount=0;
i=j;
j++;
level[j]=0;
}
}
printf("\n");
}
void main()
{
int level;
int number;
int length;
BiTree BST;
printf("*************************************************\n");
printf(" 输出二叉树第n层结点数目的算法 \n");
printf("*************************************************\n");
printf("输入的待建二叉树序列为:");
printf("%s",ch);
printf("\n");
CreateBiTree(BST);
printf("\n");
length=depth(BST);
printf("输出此二叉树的深度为:%d\n",length);
printf("\n");
printf("请输入二叉树的level层(level<=%d,输出的为二叉树的第level+1层结点数目):",length);
scanf("%d",&number);
printf("\n");
printf("输出二叉树第%d层的结点数目:\n",number+1);
LevelTraverse(BST,number);
printf("\n");
free(BST);
}
运行结果如下: