当前位置:文档之家› 数据结构与算法--树的应用

数据结构与算法--树的应用

实验报告
课程名称:数据结构与算法
实验名称:树的应用
一、实验目的
⑴、掌握二叉树的静态数组存放。

⑵、掌握哈夫曼编码的基本概念。

⑶、掌握哈夫曼编码树的构造方法。

⑷、掌握哈夫曼编码的构造和使用。

⑸、理解前缀编码的概念。

二、实验内容
⑴、按照字符出现概率构造一个哈夫曼树。

要求输入为一个文本文件(可以限
制文本仅仅包含字母),通过统计字符出现的次数计算概率,在此基础上构造哈夫曼树。

⑵、打印出每一个字母对应的哈夫曼编码。

三、实验环境
硬件:Windows XP计算机、鼠标、键盘、显示器
开发环境:Microsoft Visual C++ 6.0
四、实验步骤
①、点击开始菜单中的程序-Microsoft Visual C++ 6.0
点击菜单栏中的文件—新建—文件—C++ Source File ,在文件名(N)中写入5.cpp,再点击确定.
②、编写程序如下:
#include<stdio.h>
#define MAXV ALUE 10000//定义最大权值
#define MAXLEAF 100//定义哈夫曼树中最大叶子节点个数
#define MAXNODE MAXLEAF*2-1//哈夫曼树的最大节点数
#define MAXBIT 30//定义哈夫曼编码的最大长度
#define MAX 100
typedef struct
{
int weight;
int parent,lchild,rchild;
}HufNodeType;
typedef struct
{
int bit[MAXBIT];
int start;//编码的起位
}HufCodeType;//哈夫曼编码的结构体
void HuffmanTree(HufNodeType HuffNode[],int *w,int n)//建立哈夫曼树
{
int i;
for(i=1;i<=n;i++,w++)//对数组1~n初始化,0号单元未使用,就是构造n棵二叉树的集合
{
HuffNode[i].weight=*w;
HuffNode[i].parent=0;
HuffNode[i].lchild=0;
HuffNode[i].rchild=0;
}
for(i=n+1;i<=2*n-1;i++)//对数组n+1~2n-1进行初始化
{
HuffNode[i].weight=0;
HuffNode[i].parent=0;
HuffNode[i].lchild=0;
HuffNode[i].rchild=0;
}
for(i=n+1;i<=2*n-1;i++)//构造哈夫曼树,在数组1~i-1中选择parent值最小的两个节点,其序号为x1和x2;
{
int x1,x2,m1,m2,j;
m1=m2=MAXV ALUE;
x1=x2=0;
for(j=1;j<i;j++)
{
if(HuffNode[j].weight<m1&&HuffNode[j].parent==0)
{ m2=m1;
x2=x1;
m1=HuffNode[j].weight;
x1=j;
}
else if(HuffNode[i].weight<m2&&HuffNode[j].parent==0)
{
m2=HuffNode[j].weight;
x2=j;
}
}
HuffNode[x1].parent=i;
HuffNode[x2].parent=i;
HuffNode[i].weight=HuffNode[x1].weight+HuffNode[x2].weight;
HuffNode[i].lchild=x1;
HuffNode[i].rchild=x2;
}
}
void HuffmanCode( int w[],int n)//生成哈夫曼编码
{
int i,j,c,p;
HufNodeType HuffNode[MAXNODE];
HufCodeType HuffCode[MAXLEAF],cd;
HuffmanTree(HuffNode,w,n);//建立哈夫曼树,在HuffmanCode函数中调用HuffmanTree
for(i=1;i<=n;i++)//求n个叶子结点的哈夫曼编码
{
cd.start=n;
c=i;//对于第i个叶子结点
p=HuffNode[c].parent;//求出叶子结点的双亲
while(p!=0)//由叶子结点向上直到树根
{
if(HuffNode[p].lchild==c)
cd.bit[cd.start]=1;//左分支
else
cd.bit[cd.start]=0;//右分支
cd.start--;
c=p;
p=HuffNode[c].parent;//继续往上求双亲
}//while
for(j=cd.start;j<=n;j++)//保存求出的每个叶结点的哈夫曼编码
HuffCode[i].bit[j]=cd.bit[j];
HuffCode[i].start=cd.start+1;//求每个字母编码的起位
}
for(i=1;i<=n;i++)//输出每个叶子结点的哈夫曼编码
{
printf("第%d个叶子节点的哈夫曼编码是:",i);
for(j=HuffCode[i].start;j<=n;j++)//每个叶子节点的编码都从起位开始
{
printf("%d",HuffCode[i].bit[j]);
}
printf("\n");
}
}
void calculate(char s[])//构造函数计算输入的字符串中每个字符出现的次数
{
char ch[MAX];//记录出现的字符
int num[MAX]={0};//记录每个字符出现的次数
int i,j,n=0;
for(i=0;s[i]!='\0';i++)
{
for(j=0;j<n;j++)
if(s[i]==ch[j]||(ch[j]>='a'&&ch[j]<='z'&&s[i]+32==ch[j])) break;//判断该字符是否已经出现过
if(j<n)//该字符出现过,对应的记数器num[j]加1
num[j]++;
else//该字符是新出现的字符,记录到ch[j]中,对应计数器num[j]加1
{
if(s[i]>='A'&&s[i]<='Z')
ch[j]=s[i]+32;
else
ch[j]=s[i];
num[j]++;
n++;//出现的字符的种类数加1
}
}
for(i=0;i<n;i++)//输出
{
printf("\'%c\'的权值是%d\n",ch[i],num[i]);
}
HuffmanCode(num,n);//在calculate函数中调用HuffmanCode函数
}
void main()
{
HufNodeType HuffNode[MAXNODE];
int i=0;
char s[MAX];
printf("请输入一个字符串:");
while((s[i]=getchar())!='\n')//输入字符串
i++;
s[i]='\0';
calculate(s); //调用函数计算输入的字符串中每个字符出现的次数
}
五、实验结果
实验结果如下图所示:
六、实验总结
①.本实验主要的思路是
a)、输入字符串,构造一个函数求出字符串中每个字符出现的次数,并以此
作为每个字符的权值。

b)、构造哈弗曼树,在上一步中求出的不重复的字符的个数作为叶子结点数,
字符个数作为相对应的叶子结点的权值。

c)、构造哈弗曼编码,在哈弗曼树的基础上,选出权值最小且双亲为0的两
个结点,对其左右分别赋值为0.1,以此类推,得出每个字符的哈弗曼编码。

②.在求每个哈弗曼编码时应注意每个编码的起位。

③.在对结点进行初始化时应注意,只有叶子结点有权值,其余的并没有权值。

相关主题