实验报告五.docx
《实验报告五.docx》由会员分享,可在线阅读,更多相关《实验报告五.docx(33页珍藏版)》请在冰豆网上搜索。
实验报告五
实验编号:
5四川师大《数据结构》实验报告2015年12月28日
计算机科学学院2014级4班实验名称:
实验五:
二叉树及其应用
姓名:
张俊学号:
*******454指导老师:
_廖雪花_实验成绩:
_____
实验五二叉树及其应用
一.实验目的及要求
(1)通过实验掌握二叉树的两种基本的存储结构,及二叉树的建立、遍历,并加以应用。
(2)Huffman树建立、编码。
二.实验内容
(1)按先序次序输入二叉树中结点的值,建立一棵以二叉链表作存储结构的二叉树,然后按先序、中序、后序顺序分别遍历这棵二叉树,并完成二叉树的相应信息的统计(如各种结点数目、二叉树的高度等);
(2)建立一棵二叉排序树,并对其进行先序、中序、后序遍历。
(3)应用队列结构实现二叉树的层次遍历。
(4)设计一个完整的编码系统:
针对一篇文档,统计各个字符的出现次数,并为其设计Huffman编码。
三.实验主要流程、基本操作或核心代码、算法片段(该部分如不够填写,请另加附页)
(1)按先序次序输入二叉树中结点的值,建立一棵以二叉链表作存储结构的二叉树,然后按先序、中序、后序顺序分别遍历这棵二叉树,并完成二叉树的相应信息的统计(如各种结点数目、二叉树的高度等);
Ø程序代码部分:
//main.cpp
#include
#include"c.h"
#include
intmain()
{
BiTreeT;
printf("请直接输入字符,不要以空格隔开,输完后直接按enter\n");
printf("例如ab#d##c#e##(enter)\n");
if(CreateBiTree(T))
printf("按先序建立二叉树成功\n");
printf("先序建立的二叉树的深度为%d\n",Depth(T));
printf("先序建立的二叉树的叶子结点数为%d\n",leafnum(T));
printf("先序建立的二叉树的总结点数为%d\n",num(T));
printf("先序建立的二叉树的单分支数为%d\n",Singlenum(T));
printf("先序建立的二叉树的双分支数为%d\n",Doublenum(T));
printf("先序递归遍历二叉树:
\n");
PreorderTraverse(T,PrintTElement);
printf("\n");
printf("中序递归遍历二叉树:
\n");
InorderTraverse(T,PrintTElement);
printf("\n");
printf("后序递归遍历二叉树:
\n");
PostorderTraverse(T,PrintTElement);
printf("\n");
system("pause");
return0;
}
//b.cpp
#include
#include"c.h"
#include
#include
StatusCreateBiTree(BiTree&T)
{
TElemTypech;
scanf("%c",&ch);
if(ch=='#')
{
T=NULL;
}
else
{
T=(BiTNode*)malloc(sizeof(BiTNode));
if(!
T)
exit(OVERFLOW);
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
returnOK;
}
StatusPreorderTraverse(BiTreeT,Status(*visit)(TElemTypee))
{
if(!
T)
returnERROR;
else
{
visit(T->data);
PreorderTraverse(T->lchild,visit);
PreorderTraverse(T->rchild,visit);
}
returnOK;
}
StatusInorderTraverse(BiTreeT,Status(*visit)(TElemTypee))
{
if(!
T)
returnERROR;
else
{
InorderTraverse(T->lchild,visit);
visit(T->data);
InorderTraverse(T->rchild,visit);
}
returnOK;
}
StatusPostorderTraverse(BiTreeT,Status(*visit)(TElemTypee))
{
if(!
T)
returnERROR;
else
{
PostorderTraverse(T->lchild,visit);
PostorderTraverse(T->rchild,visit);
visit(T->data);
}
returnOK;
}
StatusPrintTElement(TElemTypee)
{
printf("%c",e);
returnOK;
}
StatusDepth(BiTreeT)//二叉树的深度
{
intdepthval,depthleft,depthright;
if(!
T)
depthval=0;
else
{
depthleft=Depth(T->lchild);
depthright=Depth(T->rchild);
depthval=1+(depthleft>depthright?
depthleft:
depthright);
}
returndepthval;
}
Statusleafnum(BiTreeT)//二叉树的叶子结点数
{
intleafnumber;
if(!
T)
leafnumber=0;
elseif(T->lchild==NULL&&T->rchild==NULL)
leafnumber=1;
else
{
leafnumber=leafnum(T->lchild)+leafnum(T->rchild);/*简写
num1=leafnum(T->lchild)
num2=leafnum(T->rhild)
leafnumber=num1+num2
*/
}
returnleafnumber;
}
Statusnum(BiTreeT)//二叉树的总的结点数
{
intnumber=0,num1,num2=0;//记住递归时一趟是要到最后的}然后再返回到调用递归函数处
if(!
T)
number=0;
else
{
num1=num(T->lchild);
num2=num(T->rchild);
number=1+num1+num2;//number=1+num(T->lchild)+num(T->rchild);
}
returnnumber;
}
StatusDoublenum(BiTreeT)
{
intnum=0,num1=0,num2=0;
if(!
T)
{
num=0;
}
elseif(T->lchild&&T->rchild)
{
num=1;
num1=Doublenum(T->lchild);
num2=Doublenum(T->rchild);
num+=num1+num2;
}
returnnum;
/*intnum1,num2;
if(!
T)
{
return0;
}
num1=Doublenum(T->lchild);
num2=Doublenum(T->rchild);
if(T->lchild!
=NULL&&T->rchild!
=NULL)
{
returnnum1+num2+1;//递归左右加本来这个不为双分支1
}
else
{
returnnum1+num2;
}*/
}
StatusSinglenum(BiTreeT)
{
if(!
T)
{
return0;
}
elseif(!
T->lchild&&T->rchild)//只有右分支
{
returnSinglenum(T->rchild)+1;//递归右分支+左分支的1
}
elseif(T->lchild&&!
T->rchild)//只有左分支
{
returnSinglenum(T->lchild)+1;//递归左分支+右分支的1
}
else//左右分支都有
{
returnSinglenum(T->lchild)+Singlenum(T->rchild);
}
}
//c.h
#ifndefc
#definec
#defineOK1
#defineERROR0
#defineOVERFLOW-1
typedefintStatus;
typedefcharTElemType;
typedefstructBiTNode{
TElemTypedata;
structBiTNode*lchild;
structBiTNode*rchild;
}BiTNode,*BiTree;
StatusCreateBiTree(BiTree&T);//创建二叉树
StatusPreorderTraverse(BiTreeT,Status(*visit)(TElemTypee));//前序遍历二叉树
StatusInorderTraverse(BiTreeT,Status(*visit)(TElemTypee));//中序遍历二叉树
StatusPostorderTraverse(BiTreeT,Status(*visit)(TElemTypee));//后序遍历二叉树
StatusPrintTElement(TElemTypee);//打印出结点值
StatusDepth(BiTreeT);//二叉树的深度
Statusleafnum(BiTreeT);//二叉树的叶子结点数
Statusnum(BiTreeT);//二叉树的总的结点数
StatusSinglenum(BiTreeT);
StatusDoublenum(BiTreeT);
#endif
Ø运行结果:
(2)建立一棵二叉排序树,并对其进行先序、中序、后序遍历。
Ø程序代码部分:
//main.cpp
#include
#include"c.h"
#include
intmain()
{
BiTreeT;
CreatBST(T);
printf("前序:
\n");
PreorderTraverse(T);
printf("\n");
printf("中序:
\n");
InorderTraverse(T);
printf("\n");
printf("后序\n");
PostorderTraverse(T);
system("pause");
return0;
}
//a.cpp
#include
#include"c.h"
#include
StatusCreatBST(BiTree&T)
{
intn,i,a[100];
printf("请输入你要建立的二叉排序树树的个数\n");
scanf("%d",&n);
while(n<=0)
{
printf("输入不合法,请重新输入元素个数\n");
scanf("%d",&n);
}
printf("请输入元素值\n");
T=NULL;//初始化树
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
Insert(T,a[i]);
}
returnOK;
}
/*
当二叉排序树T中不存在为e的数据元素,插入e
*/
StatusInsert(BiTree&T,TElemTypee)
{
BiTrees,p;
if(!
SearchBST(T,e,NULL,p))//查找不成功,则进行插入
{
s=(BiTNode*)malloc(sizeof(BiTNode));
s->data=e;
s->lchild=s->rchild=NULL;
if(!
p)//当二叉排序树为空时,插入的结点s作为根结点
{
T=s;
}
elseif(edata)
{
p->lchild=s;
}
else
{
p->rchild=s;
}
returntrue;
}
else//查找成功,不插入,返回false
{
returnfalse;
}
}
/*
在根指针T所指向的二叉排序树中递归地查找其关键字等于e的数据元素,若查找承成功,则指针p指向该数据元素结点,并返回true;
否则指针p指向查找路径上访问的最后一个结点并返回false,指针f指向T的双亲,其初始调用值为NULL
*/
boolSearchBST(BiTreeT,TElemTypee,BiTreef,BiTree&p)
{
if(!
T)//树为空,查找不成功,返回false
{
p=f;
returnfalse;
}
elseif(e==T->data)//从根开始,查找成功,指针p指向该结点,并返回true
{
p=T;
returntrue;
}
elseif(edata)
{
returnSearchBST(T->lchild,e,T,p);//此时f为双亲,即T
}
elseif(e>T->data)
{
returnSearchBST(T->rchild,e,T,p);
}
}
StatusPreorderTraverse(BiTreeT)
{
if(T)
{
printf("%d",T->data);
PreorderTraverse(T->lchild);
PreorderTraverse(T->rchild);
}
returnOK;
}
StatusInorderTraverse(BiTreeT)
{
if(T)
{
InorderTraverse(T->lchild);
printf("%d",T->data);
InorderTraverse(T->rchild);
}
returnOK;
}
StatusPostorderTraverse(BiTreeT)
{
if(T)
{
PostorderTraverse(T->lchild);
PostorderTraverse(T->rchild);
printf("%d",T->data);
}
returnOK;
}
//c.h
#ifndefc
#definec
#defineOK1
#defineERROR0
typedefintStatus;
typedefintTElemType;
typedefstructBiTNode{
TElemTypedata;
structBiTNode*lchild;
structBiTNode*rchild;
}BiTNode,*BiTree;
StatusCreatBST(BiTree&T);
StatusInsert(BiTree&T,TElemTypee);
boolSearchBST(BiTreeT,TElemTypee,BiTreef,BiTree&p);
StatusPreorderTraverse(BiTreeT);
StatusInorderTraverse(BiTreeT);
StatusPostorderTraverse(BiTreeT);
#endif
Ø运行结果:
(3)应用队列结构实现二叉树的层次遍历。
Ø代码:
//main.cpp
#include
#include
#include"c.h"
intmain()
{
BiTreeT;
printf("请输入数据元素值,不以空格分开,没有的元素以#代替\n");
printf("例如abc##de#g##f###(enter)\n");
CreatBiTree(T);
printf("层次遍历为:
\n");
LevelBiTree(T);
system("pause");
return0;
}
//a.cpp
#include
#include
#include"c.h"
StatusCreatBiTree(BiTree&T)//按先序建立二叉树
{
charch;
scanf("%c",&ch);
if(ch=='#')
T=NULL;
else
{
T=(BiTNode*)malloc(sizeof(BiTNode));
T->data=ch;
CreatBiTree(T->lchild);
CreatBiTree(T->rchild);
}
returnOK;
}
StatusLevelBiTree(BiTreeT)//按层次遍历二叉树
{
LinkQueueQ;
BiTreeb;
InitQueue(Q);
if(T)//若树不为空
{
EnQueue(Q,T);
while(!
QueueEmpty(Q))
{
DeQueue(Q,b);
if(b->lchild)
{
EnQueue(Q,b->lchild);//养成好习惯,加括号
}
if(b->rchild)
{
EnQueue(Q,b->rchild);
}
}
}
returnOK;
}
StatusInitQueue(LinkQueue&Q)
{
Q.front=Q.rear=(QNode*)malloc(sizeof(QNode));
Q.front->next=NULL;
returnOK;
}
StatusDeQueue(LinkQueue&Q,BiTree&b)
{
QNodePtrp;
if(QueueEmpty(Q))
returnERROR;
else
{
p=Q.front->next;
b=p->Qdata;
printf("%c",b->data);
Q.front->next=p->next;//
if(p==Q.rear)
{
Q.rear=Q.front;
}
free(p);
}
returnOK;
}
StatusEnQueue(LinkQueue&Q,BiTreee)
{
QNodePtrp;
p=(QNode*)malloc(sizeof(QNode));
if(!
p)
returnERROR;
p->Qdata=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;//修改指针
}
StatusQueueEmpty(LinkQueueQ)
{
if(Q.front==Q.rear)
returnOK;
else
returnERROR;
}
//c.h
#ifndefc
#definec
#defineOK1
#defineERROR0
typedefintStatus;
typedefcharTElemType;
typedefstructBiTNode{
TElemTypedata;
structBiTNode*lchild;
structBiTNode*rchild;
}BiTNode,*BiTree;
typedefstructQNode{
BiTreeQdata;
structQNode*next;
}QNode,*QNodePtr;
typedefstruct{
QNodePtrfront;
QNodePtrrear;
}LinkQueue;
StatusCreatBiTree(BiTree&T);
StatusLevelBiTree(BiTreeT);
StatusInitQueue(LinkQueue&Q);
StatusDeQueue(LinkQueue&Q,BiTree&b);
StatusEnQueue(LinkQueue&Q,BiTreee);
StatusQueueEmpty(LinkQueueQ);
#endif
Ø运行截图:
(5)设计一个完整的编码系统:
针对一篇文档,统计各个字符的出现次数,并为其设计Huffman编码。
Ø代码:
#include
#include
#include
#include
usingnamespacestd;
#define_CRT_SECURE_NO_WARNINGS
structHuffmanTree
{
intweight;
intparent,lchild,rchild;
charch;
};
typedefchar**HuffmanCode;
structreturn_value_sel
{
intre_s1;
intre_s2;
};
structreturn_value_def
{
charre_p[100];
int*re_in;
intre_count;
};
structr