实验三二叉树资料.docx
《实验三二叉树资料.docx》由会员分享,可在线阅读,更多相关《实验三二叉树资料.docx(20页珍藏版)》请在冰豆网上搜索。
实验三二叉树资料
南昌大学实验报告
---(3)二叉树
学生姓名:
罗明学号:
6100411055专业班级:
计算机111班
实验类型:
■验证□综合□设计□创新实验日期:
2013/5/2实验成绩:
一、实验目的
1.熟悉二叉树的存储结构的特性,以及如何应用树结构解决具体问题
2.掌握二叉树的基本的存储结构,以及各种操作的算法实现(如建立、遍历)以及应用
3.注意递归算法和非递归算法的设计以及赫夫曼树的应用
二、实验内容
1.按先序次序输入二叉树中结点的值,建立一棵以二叉链表作存储结构的二叉树
2.按先序、中序、后序顺序分别遍历这棵二叉树。
注意,用递归的方法实现先序遍历,用非递归的方法实现中序和后序遍历
3.编写一个求二叉树叶子结点数和二叉树的深度的算法。
4.实现二叉树的线索化
5.构建赫夫曼树,实现赫夫曼编码
三、实验要求
实现二叉树的初始化,并设计出基本操作的算法
四、实验环境
PC微机
Windows 操作系统
VisualC++6.0程序集成环境
五、程序代码
1.二叉树的存储结构及遍历二叉树
//-------函数结果状态代码----------
//common.h
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
#defineOVERFLOW-2
typedefintStatus;
//-------二叉树的二叉链表存储结构---------
//BiTree.h
typedefstructBiTNode{
TElemTypedata;
structBiTNode*lchild;//左孩子指针
structBiTNode*rchild;//右孩子指针
}BiTNode,*BiTree;
//-------栈的链式存储结构---------
//LinkStack.h
#defineSTACK_INIT_SIZE20//存储空间初始分配量
#defineSTACKINCREMENT2//存储空间分配增量
typedefstructnode{
SElemTypedata;
structnode*next;
}LinkStack;//链式栈的结构体定义
//-------基本操作的函数原型说明--------
//关于树的
intPreCreateBiTree(BiTree&T);
StatusVISIT(TElemTypee);
StatusPreOrderTraverse(BiTreeT,Status(*visit)(TElemTypee));
StatusInOrderTraverse(BiTreeT,Status(*visit)(TElemTypee));
voidMidVisit(BiTree&T);
voidPostOrderTraverse(BiTreeT,Status(*visit)(TElemTypee));
voidPostOrder(BiTNode*T,Status(*visit)(TElemTypee));
StatusCountLeaf(BiTreeT);
intdeep(BiTreeT);
//关于栈的
StatusInitStack(LinkStack**S);
StatusPush(LinkStack*S,SElemTypex);
StatusPop(LinkStack*S,SElemType&e);
StatusStackEmpty(LinkStack*S);
StatusGetTop(LinkStack*S,SElemType&e);
//--------基本操作的实现-----------
//bitree.cpp
#include
#include
#include
#include"common.h"
typedefcharTElemType;
#include"BiTree.h"
typedefBiTreeSElemType;
#include"LinkStack.h"
intn=0;
//构造而二叉链表表示的二叉树
//插入元素,按先序次序输入二叉树中结点的值(一个字符),空格字符表示空树
intPreCreateBiTree(BiTree&T)//递归先序建立{
chare;
scanf("%c",&e);
if(e==''){
T=NULL;
return1;
}
T=(BiTree)malloc(sizeof(BiTNode));
if(!
T)
exit(OVERFLOW);
T->data=e;//生成根结点
PreCreateBiTree(T->lchild);//构造左子树
PreCreateBiTree(T->rchild);//构造右子树
returnOK;
}
//访问树中元素
StatusVISIT(TElemTypee){
printf("%c",e);
returnOK;
}
//采用递归先序遍历二叉树
StatusPreOrderTraverse(BiTreeT,Status(*visit)(TElemTypee)){
if(T){
if((*visit)(T->data))
if(PreOrderTraverse(T->lchild,VISIT))
if(PreOrderTraverse(T->rchild,VISIT))returnOK;
returnERROR;
}
else
returnOK;
}
//采用中序非递归遍历二叉树
StatusInOrderTraverse(BiTreeT,Status(*visit)(TElemTypee)){
LinkStack*S;
BiTreep;
InitStack(&S);Push(S,T);//根指针进栈
while(!
StackEmpty(S)){
while(GetTop(S,p)&&p)
Push(S,p->lchild);//向左走到尽头
Pop(S,p);
if(!
StackEmpty(S))
{//访问节点,向右一步
Pop(S,p);
if(!
VISIT(p->data))
returnERROR;
Push(S,p->rchild);
}
}
returnOK;
}
//网上查的
voidMidVisit(BiTree&T)//递归中序遍历{
if(!
T)
return;
MidVisit(T->lchild);
printf("%c",T->data);
MidVisit(T->rchild);
}
//采用递归后序遍历二叉树(网上查的)
voidPostOrderTraverse(BiTreeT,Status(*visit)(TElemTypee)){
if(T){
PostOrderTraverse(T->lchild,VISIT);
PostOrderTraverse(T->rchild,VISIT);
VISIT(T->data);
}
}
//采用非递归后序遍历二叉树(网上查的)
voidPostOrder(BiTNode*T,Status(*visit)(TElemTypee)){
BiTNode*p=T;
BiTNode*stack[30];
intnum=0;
BiTNode*have_visited=NULL;
while(NULL!
=p||num>0){
while(NULL!
=p){
stack[num++]=p;
p=p->lchild;
}
p=stack[num-1];
if(NULL==p->rchild||have_visited==p->rchild){
VISIT(p->data);
num--;
have_visited=p;
p=NULL;
}
else{
p=p->rchild;
}
}
}
//统计二叉树的叶子数
StatusCountLeaf(BiTreeT){
if(T){
if(!
(T->lchild)&&!
(T->rchild))
n++;
CountLeaf(T->lchild);
CountLeaf(T->rchild);
}
returnn;
}
//统计二叉树的深度
intdeep(BiTreeT){
intld,rd;
if(T){
ld=deep(T->lchild);
rd=deep(T->rchild);
return(ld+1)>(rd+1)?
(ld+1):
(rd+1);
}
else
returnERROR;
}
//--------基本操作的实现-----------
//linkstack.cpp
#include
#include
#include
#include"common.h"
typedefcharTElemType;
#include"BiTree.h"
typedefBiTreeSElemType;
#include"LinkStack.h"
//初始化一个带头结点的空栈
StatusInitStack(LinkStack**S){
*S=(LinkStack*)malloc(sizeof(LinkStack));
if(*S==NULL)
exit(OVERFLOW);
(*S)->next=NULL;
returnOK;
}
//入栈操作,将x的数据元素插入栈s中,使x成为新的栈顶元素
StatusPush(LinkStack*S,SElemTypex){
LinkStack*p,*q;
q=S;
p=(LinkStack*)malloc(sizeof(LinkStack));
if(!
p)
exit(OVERFLOW);
p->data=x;
p->next=NULL;
while(q->next)
q=q->next;
q->next=p;
returnOK;
}
//出栈操作,先将栈s的栈顶结点的值送到e所指向的内存单元,然后删除栈顶结点
StatusPop(LinkStack*S,SElemType&e){
LinkStack*p,*q;
p=S;
if(S->next==NULL)
returnERROR;
while(p->next){
q=p;
p=p->next;
}
q->next=NULL;
e=p->data;
free(p);
returnOK;
}
//判断栈是否为空
StatusStackEmpty(LinkStack*S){
if(S->next==NULL)
returnTRUE;
else
returnFALSE;
}
//取栈顶元素
StatusGetTop(LinkStack*S,SElemType&e){
LinkStack*p,*q;
p=S;
if(S->next==NULL)
returnERROR;
while(p->next){
q=p;
p=p->next;
}
e=p->data;
returnOK;
}
//--------主程序--------
//main.cpp
#include
#include
#include"common.h"
typedefcharTElemType;
#include"BiTree.h"
typedefBiTreeSElemType;
#include"LinkStack.h"
voidmain(){
BiTreeT;
intHeight,Num;//树的深度和叶子个数
printf("按先序次序输入二叉树中结点的值,空格表示空树。
请输入:
\n");
PreCreateBiTree(T);
printf("先序遍历得到的序列为:
");
PreOrderTraverse(T,VISIT);
printf("\n");
printf("中序遍历得到的序列为:
");
//MidVisit(T);//递归中序遍历
//printf("\n");
InOrderTraverse(T,VISIT);
printf("\n");
printf("后序遍历得到的序列为:
");
PostOrder(T,VISIT);
printf("\n");
//PostOrderTraverse(T,VISIT);//递归后序遍历
//printf("\n");
Num=CountLeaf(T);
Height=deep(T);
printf("此树的深度和叶子个数分别为:
%d%d\n",Height,Num);
}
2.线索二叉树
//-------函数结果状态代码----------
//common.h
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
#defineOVERFLOW-2
typedefintStatus;
//-------二叉树的二叉线索存储表示---------
//BiThrTree.h
typedefenum{Link,Thread}PointerTag;//Link==0,表示指针;Thread==1,表示线索
typedefstructBiThrNode{
TElemTypedata;
structBiThrNode*lchild,*rchild;//左右孩子指针
PointerTagLTag,RTag;//左右标志
}BiThrNode,*BiThrTree;
//-------基本操作的函数原型说明--------
BiThrTreePreCreateBiTree();
voidInThreading(BiThrTreep);
BiThrTreeInOrderThreading(BiThrTree&t,BiThrTreeT);
BiThrTreeInOrderThrTree(BiThrTreeT);
voidInThrTravel(BiThrTreeThre);
//--------基本操作的实现-----------
//bithrtree.cpp
#include
#include
#include
#include"common.h"
typedefcharTElemType;
#include"BiThrTree.h"
BiThrTreepre;
//构造而二叉链表表示的二叉树
//插入元素,按先序次序输入二叉树中结点的值(一个字符),空格字符表示空树
BiThrTreePreCreateBiTree()//递归先序建立{
BiThrTreeT;
chare;
scanf("%c",&e);
if(e=='')
T=NULL;
else{
T=(BiThrTree)malloc(sizeof(BiThrNode));
T->data=e;
T->LTag=Link;/*初始化时指针标志均为Link*/
T->RTag=Link;
T->lchild=PreCreateBiTree();
T->rchild=PreCreateBiTree();
}
returnT;
}
voidInThreading(BiThrTreep){
if(p){
InThreading(p->lchild);//左子树线索化
if(!
p->lchild)
{//前驱线索
p->LTag=Thread;
p->lchild=pre;
}
if(!
pre->rchild)
{//后继线索
pre->RTag=Thread;
pre->rchild=p;
}
pre=p;//保持pre指向p的前驱
InThreading(p->rchild);//右子树线索化
}
}
//中序遍历二叉树T,并将其中序线索化,Thrt指向头结点
BiThrTreeInOrderThreading(BiThrTree&t,BiThrTreeT){
t=(BiThrTree)malloc(sizeof(BiThrNode));
if(!
t)
exit(OVERFLOW);
t->LTag=Link;t->RTag=Thread;//建头结点
t->rchild=t;//右指针回指
if(!
T)
t->lchild=t;
else{
t->lchild=T;
pre=t;
InThreading(T);//中序遍历进行中序线索化
pre->rchild=t;pre->RTag=Thread;//最后一个结点线索化
t->rchild=pre;
}
returnt;
}
//网上找的
BiThrTreeInOrderThrTree(BiThrTreeT)/*中序线索化二叉树*/{
BiThrTreeThre;/*Thre为头结点的指针*/
Thre=(BiThrTree)malloc(sizeof(BiThrNode));
Thre->lchild=T;
Thre->rchild=Thre;
pre=Thre;
InThreading(T);
pre->RTag=Thread;
pre->rchild=Thre;
Thre->rchild=pre;
returnThre;
}
//网上找的
/*中序遍历二叉树*/
voidInThrTravel(BiThrTreeThre){
BiThrTreep;
p=Thre->lchild;
while(p!
=Thre)/*指针回指向头结点时结束*/
{
while(p->LTag==Link)
p=p->lchild;
printf("%c",p->data);
while(p->RTag==Thread&&p->rchild!
=Thre){
p=p->rchild;
printf("%c",p->data);
}
p=p->rchild;
}
}
//--------主程序--------
//main.cpp
#include
#include
#include
#include"common.h"
typedefcharTElemType;
#include"BiThrTree.h"
voidmain(){
BiThrTreeT,Thre,t;
printf("先序初始化二叉树:
\n");
T=PreCreateBiTree();
Thre=InOrderThreading(t,T);
//Thre=InOrderThrTree(T);//网上找的
printf("中序遍历线索化后的二叉树:
\n");
InThrTravel(Thre);
printf("\n");
}
3.赫夫曼树和赫夫曼编码
//-------函数结果状态代码----------
//common.h
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
#defineOVERFLOW-2
typedefintStatus;
//-------赫夫曼树和赫夫曼编码的存储表示---------
//HuffmanTree.h
typedefstruct{
unsignedintweight;//权
unsignedintparent,lchild,rchild;
}HTNode,*HuffmanTree;//动态分配数组存储赫夫曼树
typedefchar**HuffmanCode;//动态分配数组存储赫夫曼编码表
//-------基本操作的函数原型说明--------
intMIN(HuffmanTreet,inti);
voidSelect(HuffmanTreet,intn,int&s1,int&s2);
voidHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,int*w,intn);
//--------基本操作的实现-----------
//huffmantree.cpp
#include
#include
#include
#include
#include"common.h"
#include"HuffmanTree.h"
//返回i个结点中权值最小的树的根结点序号
intMIN(HuffmanTreet,inti){
intj,flag;
unsignedintk=65535;/*取k为无符号整型最大值*/
for(j=1;j<=i;j++){
if(t[j].weightk=t[j].weight;
flag=j;
}
}
t[flag].parent=1;/*给选中的根结点的双亲赋1,避免第2次查找该结点*/
returnflag;
}
//在i个结点中选择2个权值最小的树的根结点序号,s1为其中序号小的那个
voidSelect(HuffmanTreet,