本关任务:以二叉链表作存储结构存储二叉树,利用先序递归遍历创建二叉树,并依次进行二叉树的前序、中序、后序递归遍历。
平台会对你编写的代码进行测试:
测试输入:
ABD##FE###CG#H##I##
预期输出:
先序遍历为:A,B,D,F,E,C,G,H,I,
中序遍历为:D,B,E,F,A,G,H,C,I,
后序遍历为:D,E,F,B,H,G,I,C,A,
#include
#include
#include "bitree.h"
TElemType Nil='#';
void visit(TElemType s)
{
printf("%c,",s);
}
void input(TElemType &s)
{
scanf("%c",&s);
}
void CreateBiTree(BiTree &T)
{ //按先序次序输入二叉树中结点的值
// 构造二叉链表表示的二叉树T。变量Nil表示空(子)树。
/********** Begin **********/
TElemType ch;
scanf("%c",&ch);
if(ch=='#')
T=NULL;
else{
T=(BiTree)malloc(sizeof(BiTNode));
if(!T)
exit(OVERFLOW);
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
/********** End **********/
}
int BiTreeEmpty(BiTree T)
{ // 初始条件:二叉树T存在。操作结果:若T为空二叉树,则返回TRUE,否则FALSE
/********** Begin **********/
if(T)
return FALSE;
else
return TRUE;
/********** End **********/
}
void ProOrderTraverse(BiTree T,void(*Visit)(TElemType))
{ // 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
// 先序遍历二叉树T的递归算法,对每个数据元素调用函数Visit
/********** Begin **********/
if(T){
Visit(T->data);
ProOrderTraverse(T->lchild,Visit);
ProOrderTraverse(T->rchild,Visit);
}
/********** End **********/
}
void InOrderTraverse(BiTree T,void(*Visit)(TElemType))
{ // 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
// 中序遍历二叉树T的递归算法,对每个数据元素调用函数Visit
/********** Begin **********/
if(T){
InOrderTraverse(T->lchild,Visit);
Visit(T->data);
InOrderTraverse(T->rchild,Visit);
}
/********** End **********/
}
void PostOrderTraverse(BiTree T,void(*Visit)(TElemType))
{ // 初始条件:二叉树T存在,Visit是对结点操作的应用函数
// 操作结果:后序递归遍历T,对每个结点调用函数Visit一次且仅一次
/********** Begin **********/
if(T){
PostOrderTraverse(T->lchild,Visit);
PostOrderTraverse(T->rchild,Visit);
Visit(T->data);
}
/********** End **********/
}
void DestoryBiTree(BiTree &T)
{ // 初始条件:二叉树T存在。操作结果:销毁二叉树T
/********** Begin **********/
if(T){
DestoryBiTree(T->lchild);
DestoryBiTree(T->rchild);
free(T);
T=NULL;
}
/********** End **********/
}
本关任务:给定一棵二叉树,计算该二叉树的高度、总节点个数和叶子节点个数。
平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。
以下是平台的测试样例:
测试输入:
ABC##D##EF###
预期输出:
该树的高度为:3
节点的数目为: 6
叶子节点的数目为: 3
测试输入:
ABCD###E#F##G##
预期输出:
该树的高度为:4
节点的数目为: 7
叶子节点的数目为: 3
#include
#include
#include "bitree.h"
int BiTreeDepth(BiTree T);//计算该二叉树的深度,返回深度值
int NodeCount(BiTree T);//计算该二叉树的总的节点个数,返回节点个数
int LeafNodeCount(BiTree T);//算该二叉树的叶子节点个数,返回叶子节点个数
int main()
{
BiTree T;
CreateBiTree(T);
printf("该树的高度为:%d\n",BiTreeDepth(T));
printf("节点的数目为: %d\n",NodeCount(T));
printf("叶子节点的数目为: %d\n",LeafNodeCount(T));
DestoryBiTree(T);
return 0;
}
int BiTreeDepth(BiTree T)
{ // 初始条件:二叉树T存在。操作结果:返回T的深度
/********** Begin **********/
int i,j;
if(!T) return 0;
if(T->lchild)
i=BiTreeDepth(T->lchild);
else
i=0;
if(T->rchild)
j=BiTreeDepth(T->rchild);
else
j=0;
return i>j?i+1:j+1;
/********** End **********/
}
int NodeCount(BiTree T)
{
//初始条件:二叉树T存在。操作结果:返回T的结点数
/********** Begin **********/
if(!T)
return 0;
else
return NodeCount(T->lchild)+NodeCount(T->rchild)+1;
/********** End **********/
}
int LeafNodeCount(BiTree T)
{
//初始条件:二叉树T存在。操作结果:返回T的叶子结点数
/********** Begin **********/
if(!T)
return 0;
else
if(!T->lchild && !T->rchild)
return 1;
else
return LeafNodeCount(T->lchild)+LeafNodeCount(T->rchild);
/********** End **********/
}
本关任务:给定一棵二叉树,借助队列实现层次遍历二叉树。
平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。
以下是平台的测试样例:
测试输入:ABC##D##EF###
预期输出:ABECDF
测试输入:ABCD###E#F##G##
预期输出:ABGCEDF
#include
#include
#include "bitree.h"
#include "linkqueue.h"
void LevelOrderTraverse(BiTree T,void(*Visit)(TElemType));
int main()
{
BiTree T;
CreateBiTree(T);
printf("层序遍历为:");
LevelOrderTraverse(T,visit);
DestoryBiTree(T);
return 0;
}
void LevelOrderTraverse(BiTree T,void(*Visit)(TElemType))
{ // 初始条件:二叉树T存在,Visit是对结点操作的应用函数
// 操作结果:层序递归遍历T(利用队列),对每个结点调用函数Visit一次且仅一次
/********** Begin **********/
LinkQueue q;
QElemType a;
if(T){
InitQueue(q);
EnQueue(q,T);
while(!QueueEmpty(q)){
DeQueue(q,a);
Visit(a->data);
if(a->lchild)
EnQueue(q,a->lchild);
if(a->rchild)
EnQueue(q,a->rchild);
}
printf("\n");
}
/********** End **********/
}
本关任务:给定一棵二叉树,使用递归的方法实现二叉树的左右子树交换,并输出交换后的二叉树的中序遍历结果。
平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。
以下是平台的测试样例:
测试输入:
ABC##D##EF###
预期输出:
交换前二叉树中序遍历:C,B,D,A,F,E,
交换后二叉树中序遍历:E,F,A,D,B,C,
输入格式说明:
输入二叉树的先序序列。一棵二叉树的先序序列是一个字符串,若字符是‘#’,表示该二叉树是空树,否则该字符是相应结点的数据元素。
输出格式说明:
输出有两行:
第一行是交换前二叉树的中序遍历序列;
第二行是交换后的二叉树的中序遍历序列。
#include
#include
#include "bitree.h"
void exchange ( BiTree T ) ; // 实现二叉树左右子树的交换(递归法)
int main()
{
BiTree T;
CreateBiTree(T);
printf("交换前二叉树中序遍历:");
InOrderTraverse(T,visit);
printf("\n");
exchange(T);
printf("交换后二叉树中序遍历:");
InOrderTraverse(T,visit);
printf("\n");
DestoryBiTree(T);
return 0;
}
void exchange ( BiTree T )
{
// 实现二叉树左右子树的交换(递归法)
/********** Begin *********/
BiTree temp;
if(T){
temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
exchange(T->lchild);
exchange(T->rchild);
}
/********** End **********/
}
本关任务:给定一棵二叉树,使用非递归的方式实现二叉树左右子树交换,并输出中序遍历结果。
平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。
以下是平台的测试样例:
测试输入:
ABC##D##EF###
预期输出:
交换前二叉树中序遍历:C,B,D,A,F,E,
交换后二叉树中序遍历:E,F,A,D,B,C,
输入格式说明:
输入二叉树的先序序列。一棵二叉树的先序序列是一个字符串,若字符是‘#’,表示该二叉树是空树,否则该字符是相应结点的数据元素。
输出格式说明:
输出有两行:
第一行是交换前二叉树的中序遍历序列;
第二行是交换后的二叉树的中序遍历序列。
#include
#include
#include "bitree.h"
#include "sqstack.h"
void exchange ( BiTree T ) ; // 实现二叉树左右子树的交换(非递归法)
int main()
{
BiTree T;
CreateBiTree(T);
printf("交换前二叉树中序遍历:");
InOrderTraverse(T,visit);
printf("\n");
exchange(T);
printf("交换后二叉树中序遍历:");
InOrderTraverse(T,visit);
printf("\n");
DestoryBiTree(T);
return 0;
}
void exchange(BiTree T)
{
// 实现二叉树左右子树的交换(栈实现)
/********** Begin *********/
SqStack s;
InitStack(s);
Push(s,T);
while(!StackEmpty(s)){
Pop(s,T);
BiTree temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
if(T->rchild)
Push(s,T->rchild);
if(T->lchild)
Push(s,T->lchild);
}
DestroyStack(s);
/********** End **********/
}
本关任务:以二叉链表作存储结构存储二叉树,利用先序递归遍历创建二叉树,并进行二叉树中序非递归遍历。
平台会对你编写的代码进行测试:
测试输入:
ABD##FE###CG#H##I##
预期输出:
中序遍历为:D,B,E,F,A,G,H,C,I,
#include
#include
#include "bitree.h"
#include "sqstack.h"
void InOrderTraverse2(BiTree T,void(*Visit)(TElemType));// 中序非递归遍历二叉树
int main()
{
BiTree T;
CreateBiTree(T);
printf("中序遍历:");
InOrderTraverse2(T,visit);
printf("\n");
DestoryBiTree(T);
return 0;
}
void InOrderTraverse2(BiTree T,void(*Visit)(TElemType))
{ // 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
// 中序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit
/********** Begin *********/
SqStack s;
InitStack(s);
while(T || !StackEmpty(s)){
if(T){
Push(s,T);
T=T->lchild;
}else{
Pop(s,T);
Visit(T->data);
T=T->rchild;
}
}
DestroyStack(s);
/********** End **********/
}
bitree.h
#ifndef __BITREE_H__
#define __BITREE_H__
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
// 二叉树的二叉链表存储表示
typedef char TElemType;
typedef struct BiTNode
{
TElemType data;
BiTNode *lchild,*rchild; // 左右孩子指针
}BiTNode,*BiTree;
void visit(TElemType s);
void input(TElemType &s);
void InitBiTree(BiTree &T); //构造空二叉树T
void CreateBiTree(BiTree &T); //按先序遍历次序输入二叉树中结点的值(字符型或整型), 构造二叉链表存储的二叉树T
int BiTreeEmpty(BiTree T); //判断二叉树T是否为空
void ProOrderTraverse(BiTree T,void(*Visit)(TElemType));//先序遍历二叉树T,对每个结点调用函数Visit一次且仅一次
void InOrderTraverse(BiTree T,void(*Visit)(TElemType)); //中序遍历二叉树T,对每个结点调用函数Visit一次且仅一次
void PostOrderTraverse(BiTree T,void(*Visit)(TElemType)); //后序遍历二叉树T,对每个结点调用函数Visit一次且仅一次
void DestoryBiTree(BiTree &T); // 销毁二叉树
#define ClearBiTree DestroyBiTree // 清空二叉树和销毁二叉树
#endif
bitree.cpp
#include
#include
#include "bitree.h"
TElemType Nil='#';
void visit(TElemType s)
{
printf("%c,",s);
}
void input(TElemType &s)
{
scanf("%c",&s);
}
void CreateBiTree(BiTree &T)
{ //按先序次序输入二叉树中结点的值
// 构造二叉链表表示的二叉树T。变量Nil表示空(子)树。
/********** Begin **********/
TElemType ch;
scanf("%c",&ch);
if(ch=='#')
T=NULL;
else{
T=(BiTree)malloc(sizeof(BiTNode));
if(!T)
exit(OVERFLOW);
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
/********** End **********/
}
int BiTreeEmpty(BiTree T)
{ // 初始条件:二叉树T存在。操作结果:若T为空二叉树,则返回TRUE,否则FALSE
/********** Begin **********/
if(T)
return FALSE;
else
return TRUE;
/********** End **********/
}
void ProOrderTraverse(BiTree T,void(*Visit)(TElemType))
{ // 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
// 先序遍历二叉树T的递归算法,对每个数据元素调用函数Visit
/********** Begin **********/
if(T){
Visit(T->data);
ProOrderTraverse(T->lchild,Visit);
ProOrderTraverse(T->rchild,Visit);
}
/********** End **********/
}
void InOrderTraverse(BiTree T,void(*Visit)(TElemType))
{ // 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
// 中序遍历二叉树T的递归算法,对每个数据元素调用函数Visit
/********** Begin **********/
if(T){
InOrderTraverse(T->lchild,Visit);
Visit(T->data);
InOrderTraverse(T->rchild,Visit);
}
/********** End **********/
}
void PostOrderTraverse(BiTree T,void(*Visit)(TElemType))
{ // 初始条件:二叉树T存在,Visit是对结点操作的应用函数
// 操作结果:后序递归遍历T,对每个结点调用函数Visit一次且仅一次
/********** Begin **********/
if(T){
PostOrderTraverse(T->lchild,Visit);
PostOrderTraverse(T->rchild,Visit);
Visit(T->data);
}
/********** End **********/
}
void DestoryBiTree(BiTree &T)
{ // 初始条件:二叉树T存在。操作结果:销毁二叉树T
/********** Begin **********/
if(T){
DestoryBiTree(T->lchild);
DestoryBiTree(T->rchild);
free(T);
T=NULL;
}
/********** End **********/
}
linkqueue.h
#ifndef __LINKQUEUE_H__
#define __LINKQUEUE_H__
#include "bitree.h"
typedef BiTNode * QElemType;
typedef struct QNode
{
QElemType data;
QNode *next;
}*QueuePtr;
struct LinkQueue
{
QueuePtr front,rear; // 队头、队尾指针
};
void InitQueue(LinkQueue &Q); // 构造一个空队列Q
void DestroyQueue(LinkQueue &Q); // 销毁队列Q,Q不再存在
void ClearQueue(LinkQueue &Q); // 将Q清为空队列
int QueueEmpty(LinkQueue Q); // 若队列Q为空队列,则返回TRUE;否则返回FALSE
int QueueLength(LinkQueue Q); // 返回Q的元素个数,即队列的长度
int GetHead(LinkQueue Q,QElemType &e); // 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR
int EnQueue(LinkQueue &Q,QElemType e); // 插入元素e为Q的新的队尾元素
int DeQueue(LinkQueue &Q,QElemType &e); // 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR
void QueueTraverse(LinkQueue Q,void(*vi)(QElemType)); // 从队头到队尾依次对队列
#endif
linkqueue.cpp
# include
# include
# include "linkqueue.h"
// 链队列的基本操作(9个)
void InitQueue(LinkQueue &Q)
{ // 构造一个空队列Q
if(!(Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode))))
exit(OVERFLOW);
Q.front->next=NULL;
}
void DestroyQueue(LinkQueue &Q)
{ // 销毁队列Q(无论空否均可)
while(Q.front)
{
Q.rear=Q.front->next;
free(Q.front);
Q.front=Q.rear;
}
}
void ClearQueue(LinkQueue &Q)
{ // 将Q清为空队列
QueuePtr p,q;
Q.rear=Q.front;
p=Q.front->next;
Q.front->next=NULL;
while(p)
{
q=p;
p=p->next;
free(q);
}
}
int QueueEmpty(LinkQueue Q)
{ // 若Q为空队列,则返回TRUE,否则返回FALSE
/********** Begin **********/
if(Q.front->next==NULL)
return TRUE;
else
return FALSE;
}
int QueueLength(LinkQueue Q)
{ // 求队列的长度
int i=0;
QueuePtr p;
p=Q.front;
while(Q.rear!=p)
{
i++;
p=p->next;
}
return i;
}
int GetHead(LinkQueue Q,QElemType &e)
{ // 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR
QueuePtr p;
if(Q.front==Q.rear)
return ERROR;
p=Q.front->next;
e=p->data;
return OK;
}
int EnQueue(LinkQueue &Q,QElemType e)
{ // 插入元素e为Q的新的队尾元素
QueuePtr p;
if(!(p=(QueuePtr)malloc(sizeof(QNode)))) // 存储分配失败
exit(OVERFLOW);
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
}
int DeQueue(LinkQueue &Q,QElemType &e)
{ // 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
QueuePtr p;
if(Q.front==Q.rear)
return ERROR;
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return OK;
/********** End **********/
}
void QueueTraverse(LinkQueue Q,void(*vi)(QElemType))
{ // 从队头到队尾依次对队列Q中每个元素调用函数vi()
QueuePtr p;
p=Q.front->next;
while(p)
{
vi(p->data);
p=p->next;
}
printf("\n");
}
sqstack.h
#ifndef __SQSTACK_H__
#define __SQSTACK_H__
#include "bitree.h"
#define STACK_INIT_SIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
typedef BiTNode * SElemType;
typedef struct
{
SElemType *base; //栈的基址即栈底指针
SElemType *top; //栈顶指针
int stacksize; //当前分配的空间
}SqStack;
void InitStack(SqStack &S); // 构造一个空栈S
void DestroyStack(SqStack &S); // 销毁栈S,S不再存在
void ClearStack(SqStack &S); // 把S置为空栈
int StackEmpty(SqStack S); // 若栈S为空栈,则返回TRUE,否则返回FALSE
int StackLength(SqStack S); // 返回S的元素个数,即栈的长度
int GetTop(SqStack S,SElemType &e); // 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
void Push(SqStack &S,SElemType e); // 插入元素e为新的栈顶元素
int Pop(SqStack &S,SElemType &e); // 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
void StackTraverse(SqStack S,void(*visit)(SElemType)); // 从栈底到栈顶依次对栈中每个元素调用函数visit()
#endif
sqstack.cpp
#include
#include
#include"sqstack.h"
void InitStack(SqStack &S)
{
if(!(S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType))))
exit(OVERFLOW); // 存储分配失败
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
}
void DestroyStack(SqStack &S)
{
free(S.base);
S.base=NULL;
S.top=NULL;
S.stacksize=0;
}
void ClearStack(SqStack &S)
{
S.top=S.base;
}
int StackEmpty(SqStack S)
{
if(S.top==S.base)
return TRUE;
else
return FALSE;
}
int StackLength(SqStack S)
{
return S.top-S.base;
}
int GetTop(SqStack S,SElemType &e)
{
if(S.top>S.base)
{
e=*(S.top-1);
return OK;
}
else
return ERROR;
}
void Push(SqStack &S,SElemType e)
{
if(S.top-S.base>=S.stacksize) // 栈满,追加存储空间
{
S.base=(SElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!S.base)
exit(OVERFLOW); // 存储分配失败
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*(S.top)++=e;
}
int Pop(SqStack &S,SElemType &e)
{
if(S.top==S.base)
return ERROR;
e=*--S.top;
return OK;
}
void StackTraverse(SqStack S,void(*visit)(SElemType))
{
while(S.top>S.base)
visit(*S.base++);
printf("\n");
}