《数据结构与算法》实验指导与报告书exp6BitreeWord格式文档下载.docx
《《数据结构与算法》实验指导与报告书exp6BitreeWord格式文档下载.docx》由会员分享,可在线阅读,更多相关《《数据结构与算法》实验指导与报告书exp6BitreeWord格式文档下载.docx(17页珍藏版)》请在冰豆网上搜索。
________。
(5)该二叉树的叶子结点数为:
___________。
(6)交换该二叉树所有结点的左右次序得到的新二叉树为:
(画出新二叉树的图)
(7)新二叉树的三种遍历序列分别为:
exp6_1.c参考程序如下:
#include<
stdio.h>
malloc.h>
#defineMAX20
/*---二叉树的二叉链表存储表示---*/
typedefstructBTNode
{
chardata;
/*结点数据*/
structBTNode*lchild;
/*左孩子指针*/
structBTNode*rchild;
/*右孩子指针*/
}*BiTree;
/*---非递归遍历辅助队列---*/
typedefstruct
BiTreedata[MAX];
intfront,rear;
}queue;
voidcreateBiTree(BiTree*t);
/*先序遍历创建二叉树*/
voidPreOrder(BiTreep);
/*先序遍历二叉树*/
voidInOrder(BiTreep);
/*中序遍历二叉树*/
voidPostOrder(BiTreep);
/*后序遍历二叉树*/
voidRPreorder(BiTreep);
/*先序遍历的非递归算法*/
voidRInorder(BiTreep);
/*中序遍历的非递归算法*/
voidRPostorder(BiTreep);
/*后序遍历的非递归算法*/
intdepth(BiTreet);
/*求二叉树的深度算法*/
BiTreegettreenode(charx,BiTreelptr,BiTreerptr);
/*后序复制二叉树-建立结点*/
BiTreecopytree(BiTreet);
/*以后序遍历的方式复制二叉树*/
BiTreeswap(BiTreeb);
/*交换二叉树的结点的左右孩子*/
voidccOrder(BiTreet);
/*利用循环队列实现层次遍历*/
intLeaves(BiTreet);
/*统计二叉树叶子结点(递归)*/
voidrelease(BiTreet);
/*释放二叉树*/
/*先序遍历创建二叉树*/
voidcreateBiTree(BiTree*t)
chars;
BiTreeq;
printf("
\npleaseinputdata:
"
);
s=getchar();
getchar();
/*扔掉存在键盘缓冲区的输入结束回车符*/
if(s=='
*'
)/*子树为空则返回*/
{
*t=NULL;
return;
}
q=(BiTree)malloc(sizeof(structBTNode));
if(q==NULL)
Memoryallocfailure!
exit(0);
q->
data=s;
*t=q;
createBiTree(&
q->
lchild);
/*递归建立左子树*/
rchild);
/*递归建立右子树*/
}/*createBiTree*/
/*先序遍历二叉树,补充递归算法*/
voidPreOrder(BiTreep)
}/*PreOrder*/
/*中序遍历二叉树,补充递归算法*/
voidInOrder(BiTreep)
}/*InOrder*/
/*后序遍历二叉树,补充递归算法*/
voidPostOrder(BiTreep)
}/*PostOrder*/
/*先序遍历的非递归算法*/
voidRPreorder(BiTreep)
BiTreestack[MAX],q;
inttop=0,i;
for(i=0;
i<
MAX;
i++)stack[i]=NULL;
/*初始化栈*/
q=p;
while(q!
=NULL)
%c"
q->
data);
if(q->
rchild!
=NULL)_______________________;
/*右指针进栈*/
lchild!
=NULL)q=q->
lchild;
/*顺着左指针继续向下*/
elseif(top>
0)q=stack[--top];
/*左子树访问完,出栈继续访问右子树结点*/
elseq=NULL;
}/*RPreorder*/
/*中序遍历的非递归算法*/
voidRInorder(BiTreep)
}/*RInorder*/
/*后序遍历的非递归算法*/
voidRPostorder(BiTreep)
inti,top=0,flag[MAX];
i++)/*初始化栈*/
stack[i]=NULL;
flag[i]=0;
=NULL||top!
=0)
if(q!
=NULL)/*当前结点进栈,先遍历其左子树*/
stack[top]=q;
flag[top]=0;
top++;
q=q->
else
while(top)
if(flag[top-1]==0)/*遍历结点的右子树*/
q=stack[top-1];
rchild;
flag[top-1]=1;
break;
q=stack[--top];
/*遍历结点*/
if(top==0)break;
}/*RPostorder*/
/*求二叉树的深度算法,补充递归算法*/
intdepth(BiTreet)
}/*depth*/
/*建立结点*/
BiTreegettreenode(charx,BiTreelptr,BiTreerptr)
BiTreet;
t=(BiTree)malloc(sizeof(structBTNode));
t->
data=x;
lchild=lptr;
rchild=rptr;
return(t);
}/*gettreenode*/
/*以后序遍历的方式递归复制二叉树*/
BiTreecopytree(BiTreet)
BiTreenewlptr,newrptr,newnode;
if(t==NULL)
returnNULL;
if(t->
newlptr=copytree(t->
elsenewlptr=NULL;
newrptr=copytree(t->
elsenewrptr=NULL;
newnode=gettreenode(t->
data,newlptr,newrptr);
return(newnode);
}/*copytree*/
/*交换二叉树的结点的左右孩子*/
BiTreeswap(BiTreeb)
BiTreet,t1,t2;
if(b==NULL)
t=NULL;
data=b->
data;
t1=swap(b->
/*递归交换左子树上的结点*/
t2=swap(b->
/*递归交换右子树上的结点*/
lchild=t2;
/*交换根t的左右子树*/
rchild=t1;
}/*swap*/
/*利用循环队列实现层次遍历*/
voidccOrder(BiTreet)
}/*ccOrder*/
/*统计二叉树叶子结点,补充递归算法*/
intLeaves(BiTreet)
}/*Leaves*/
/*释放二叉树*/
voidrelease(BiTreet)
if(t!
release(t->
free(t);
}/*release*/
intmain()
BiTreet=NULL,copyt=NULL;
intselect;
do
\n***************MENU******************\n"
1.按先序序列建立二叉树\n"
2.遍历二叉树(三种递归方法)\n"
3.遍历二叉树(三种非递归方法)\n"
4.层次遍历二叉树\n"
5.输出二叉树的深度\n"
6.统计二叉树的叶子结点数(递归)\n"
7.后序遍历方式复制一棵二叉树\n"
8.交换二叉树所有结点的左右孩子\n"
0.EXIT"
\ninputchoice:
scanf("
%d"
&
select);
switch(select)
case1:
\n1-按先序序列建立二叉树:
\n"
请依次输入结点序列:
t);
二叉树创建成功!
二叉树未创建成功!
case2:
\n2-遍历二叉树(三种递归方法):
\n先序遍历序列:
PreOrder(t);
\n中序遍历序列:
InOrder(t);
\n后序遍历序列:
PostOrder(t);
case3:
\n3-遍历二叉树(三种非递归方法):
\n先序遍历的非递归:
RPreorder(t);
\n中序遍历的非递归:
RInorder(t);
\n后序遍历的非递归:
RPostorder(t);
case4:
\n4-层次遍历二叉树:
\n按层次遍历:
ccOrder(t);
case5:
\n5-输出二叉树的深度:
\n二叉树的深度:
depth(t));
case6:
\n6-统计二叉树的叶子结点数(递归):
\n叶子结点数为:
Leaves(t));
case7:
\n7-后序遍历方式复制一棵二叉树:
copyt=copytree(t);
if(copyt!
\n先序递归遍历复制的二叉树:
PreOrder(copyt);
\n复制失败!
case8:
\n8-交换二叉树所有结点的左右孩子:
\n先序递归遍历交换后的二叉树:
PreOrder(swap(t));
/*如需输出中序和后序遍历的结果,增加调用*/
case0:
release(t);
/*释放二叉树*/
default:
while(select);
return0;
}
2、编写程序exp6_2.c,实现哈夫曼树的建立和哈夫曼编码。
若有一组字符序列{a,c,e,i,s,t,w},对应的出现频率为{10,1,15,12,3,4,13}。
以此序列创建哈夫曼树和哈夫曼编码。
回答下列问题,补充完整程序,并调试运行验证结果。
(1)构造该序列的哈夫曼树,画出哈夫曼树的形态。
(以结点值左小右大的原则)
(2)写出对应的哈夫曼编码。
(3)计算编码的WPL。
exp6_2.c程序代码参考如下:
#defineMAXVALUE10000/*定义最大权值*/
#defineMAXLEAF30/*定义哈夫曼树中叶子结点个数*/
#defineMAXNODEMAXLEAF*2-1
#defineMAXBIT10/*定义哈夫曼编码的最大长度*/
typedefstruct/*哈夫曼编码结构*/
intbit[MAXBIT];
intstart;
HCodeType;
typedefstruct/*哈夫曼树结点结构*/
chardata;
intweight;
intparent;
intlchild;
intrchild;
HNodeType;
voidHuffmanTree(HNodeTypeHuffNode[],int*hn);
voidHuffmanCode(HNodeTypeHuffNode[],HCodeTypeHuffCode[],intn);
voidHuffmanTree(HNodeTypeHuffNode[],int*hn)/*哈夫曼树的构造算法*/
inti,j,m1,m2,x1,x2,n;
n:
n);
/*输入叶子结点个数*/
for(i=0;
2*n-1;
i++)/*数组HuffNode[]初始化*/
;
HuffNode:
n;
i++)
%c,%d"
HuffNode[i].data,&
HuffNode[i].weight);
/*输入n个叶子结点的权值*/
n-1;
i++)/*构造哈夫曼树*/
m1=m2=MAXVALUE;
x1=x2=0;
for(j=0;
j<
n+i;
j++)
if(HuffNode[j].weight<
m1&
&
HuffNode[j].parent==-1)
m2=m1;
x2=x1;
m1=HuffNode[j].weight;
x1=j;
elseif(HuffNode[j].weight<
m2&
m2=HuffNode[j].weight;
x2=j;
/*将找出的两棵子树合并为一棵子树*/
HuffNode[x1].parent=n+i;
HuffNode[x2].parent=n+i;
HuffNode[n+i].weight=;
HuffNode[n+i].lchild=x1;
HuffNode[n+i].rchild=x2;
*hn=n;
voidHuffmanCode(HNodeTypeHuffNode[],HCodeTypeHuffCode[],intn)/*生成哈夫曼编码*/
HCodeTypecd;
inti,j,c,p;
i++)/*求每个叶子结点的哈夫曼编码*/
cd.start=n-1;
c=i;
p=HuffNode[c].parent;
while(p!
=-1)/*由叶结点向上直到树根*/
if(HuffNode[p].lchild==c)
/*左分支编码为0*/
/*右分支编码为1*/
cd.start--;
c=p;
for(j=cd.start+1;
j++)/*保存求出的每个叶结点的哈夫曼编码和编码的起始位*/
HuffCode[i].bit[j]=cd.bit[j];
HuffCode[i].start=cd.start;
i++)/*输出每个叶子结点的哈夫曼编码*/
%c:
"
HuffNode[i].data);
for(j=HuffCode[i].start+1;
HuffCode[i].bit[j]);
HNodeTypeHuffNode[MAXNODE];
HCodeTypeHuffCode[MAXLEAF];
intn,i;
createHuffmanTree:
HuffmanTree(HuffNode,&
putchar(HuffNode[i].data);
%3d"
HuffNode[i].weight);
HuffNode[i].parent);
HuffNode[i].lchild);
HuffNode[i].rchild);
HuffmanCode(HuffNode,HuffCode,n);
【拓展实验】
3、实现哈夫曼的解码功能。
在上题的基础上,根据给定的哈夫曼编码译文,进行解码,输出原字符编码。
【实验小结】