实验三哈夫曼编码

时间:2024.4.27

华北水利水电学院  数据结构实验报告

20122013学年  学期   2010 计算机科学与技术 专业

班级: 2010134     学号: 201013432     姓名:蔡启林     

实验三  树的应用

一、  实验题目:

树的应用——哈夫曼编码

二、 实验内容:

利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求哈夫曼编码。

从键盘输入若干字符及每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,求出各字符的哈夫曼编码。要求:

1.  输出存放哈夫曼树的数组HT的初态和终态;

2.  输出每个字符的哈夫曼编码;

3.  输入由上述若干字符组成的字符串,对电文进行编码并输出;

4.  (选作)输入电文的哈夫曼编码,进行译码并输出。

三、程序源代码:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <conio.h>

#define MAXLEAF 100

struct HTNode

{

   char letter;

   int parent;

   int lchild;

   int rchild;

   int weight;

};

struct ChNode

{

   char letter;

   int weight;

};

struct HCode

{

   char code[MAXLEAF];

   int m_start;

};

//创建哈夫曼树

void CreateHT(HTNode ht[],int n,ChNode s[])

{

   int i,k,s1,s2;

   int m1,m2;

   for (i=0;i<2*n-1;i++)

   {

       ht[i].parent=0;

       ht[i].lchild=0;

       ht[i].rchild=0;

       ht[i].weight=0;

   }

   for (i=0;i<n;i++)

   {

       ht[i].letter=s[i].letter;

       ht[i].weight=s[i].weight;

   }

   printf("哈夫曼树初态为:\n");

   printf("data weight parent lchild rchild\n");

   for (i=0;i<2*n-1;i++)

   {

       printf("%-6c %-6d %-6d %-6d %-6d\n",ht[i].letter,ht[i].weight,ht[i].parent,ht[i].lchild,ht[i].rchild);

   }

   for (i=n;i<2*n-1;i++)

   {

       m1=m2=32767;

       s1=s2=0;

       for (k=0;k<=i-1;k++)

       {

          if (ht[k].parent==0)

          {

              if (ht[k].weight<m1)

              {

                 m2=m1;

                 s2=s1;

                 m1=ht[k].weight;

                 s1=k;

              }

              else if (ht[k].weight<m2)

              {

                 m2=ht[k].weight;

                 s2=k;

              }

          }

         

       }

       ht[s1].parent=i;

       ht[s2].parent=i;

       ht[i].weight=ht[s1].weight+ht[s2].weight;

       ht[i].lchild=s1;

       ht[i].rchild=s2;

   }

   printf("\n哈夫曼树终态为:\n");

   printf("data  weight parent lchild rchild\n");

   for (i=0;i<2*n-1;i++)

   {

       printf("%-6c %-6d %-6d %-6d %-6d\n",ht[i].letter,ht[i].weight,ht[i].parent,ht[i].lchild,ht[i].rchild);

   }

   printf("\n");

}

//哈夫曼编码

void CreateCode(HTNode ht[],HCode hcd[],int n)

{

   int i,f,letter;

   HCode hc;

   for (i=0;i<n;i++)

   {

       hc.m_start=n-1;

       letter=i;

       f=ht[i].parent;

       while(f!=-1)

       {

          if(ht[f].lchild==letter)

              hc.code[hc.m_start--]='0';

          else

              hc.code[hc.m_start--]='1';

          letter=f;

          f=ht[f].parent;  

       }

       hc.m_start++;

       hcd[i]=hc;

   }

   printf("哈夫曼编码:\n");

   printf("结点信息  权值  哈夫曼编码\n");

   for (i=0;i<n;i++)

   {

       printf("  %c%s%d%s",ht[i].letter,"          ",ht[i].weight,"        ");

       for (int j=hcd[i].m_start;j<n;j++)

          printf("%c",hcd[i].code[j]);

       printf("\n");

   }

}

//译码

void Coding(HTNode ht[],HCode hcd[],int n,char str[])

{

   for (int i=0;str[i]!='\0';i++)

   {

       for (int j=0;j<n;j++)

       {

          if (str[i]==ht[j].letter)

          {

              for (int k=hcd[j].m_start;k<n;k++)

              {

                 printf("%c",hcd[j].code[k]);

              }

              break;

          }

       }

   }

   printf("\n");

}

void main()

{

   char str[MAXLEAF];

   printf("**********************欢迎使用赫夫曼编译系统**********************\n");

   printf("从键盘输入若干字符:\n");

   scanf("%s",str);

   ChNode s[20];

   memset(s,0,sizeof(ChNode)*20);

   int j=0;

   for (int i=0;str[i]!='\0';i++)

   {  

       int flag=0;

       for(int k=0;k<j;k++)

       {

          if(str[i]==s[k].letter)

          {

              s[k].weight++;

              flag=1;

              break;

          }

       }

       if(!flag)

       {

         

          s[j].letter=str[i];

          s[j].weight=1;

          j++;

       }

   }

   HTNode ht[MAXLEAF];

   memset(ht,0,sizeof(HTNode)*MAXLEAF);

   HCode hcd[MAXLEAF];

   int num=-1;

   while(1)

   {

       printf("************************ 主菜单 ********************************\n");

       printf("**                      1.创建哈夫曼树并查看初态和终态        **\n");

       printf("**                      2.创建并查看哈夫曼编码                **\n");

       printf("**                      3.译码                                **\n");

       printf("**                      4.退出                                **\n");

       printf("****************************************************************\n");

       scanf("%d",&num);

       if(num==0)

          break;

       switch (num)

       {

       case 1:

          {

              CreateHT(ht,j,s);

          }

          break;

       case 2:

          {

              CreateCode(ht,hcd,j);

          }

          break;

       case 3:

          {

              char str[MAXLEAF];

              printf("请输入译文:\n");

              scanf("%s",str);

              printf("译码后为:");

              Coding(ht,hcd,j,str);

          }

          break;

       default:

          break;

       }

       printf("按任意键继续...");

       getch();

       system("cls");

   }

}

四、测试结果:

五、小结(包括收获、心得体会、存在的问题及解决问题的方法、建议等)

注:内容一律使用宋体五号字,单倍行间距

通过这次的课程设计,我对赫夫曼树以及赫夫曼编码有了更深的认识和理解,我在设计期间遇到的难点就是开始的时候,代码中有许多的错误,特别是输出赫夫曼树的存储结构的初态和终态。后来在好好的看教材的基础上解决了这个问题,但是这个存储结构还有一些问题,在这次编译哈夫曼树的存储结构的初态和终态,使得我更加的明白了哈夫曼到底是怎么存储信息的。这次的编译过程遇到很小的知识错误,就是设置清屏时没有设置头文件,就是这个小小的错误,让我在调试程序的时候没有捕获的数据,后来修改后才解决这个问题。

许多的错误让我明白了一个道理---细心是非常重要的。同时,对于编程者而言,思路清晰是相当重要的。在适当的时候和同学一起交流探讨是一个十分好的学习机会。请教老师也很重要,因为毕竟我们是新手,对于某些问题很难弄清楚。而且,某些错误对于我们来说有时候想半天都弄不来,但老师几下下就搞好了,这样就更加有效地节约了时间。

这次的赫夫曼编码的好多代码老师已经在课堂上讲了,我曾经把教材上的代码编译运行过,感觉的确很简单,但是毕竟不是我自己做出来的,所以我自己就编译了一个与教材不同的程序,遇到的问题很多,编的也不太完美,也有一些小问题,但是确实我自己做出来的,成就感很大,让我对赫夫曼有了更深的了解,也让我对今后的学习更有信心了


第二篇:实验七哈夫曼编码


算法设计与分析实验报告

姓名:杨勇涛

班级:计科102班

一、实验名称: 哈夫曼编码

时间:20xx年4月4日,星期三,第四节

地点:12#311

二、实验目的及要求

设计任务: ?从键盘输入一串电文字符能输出对应的哈夫曼编码。同时,能翻译由哈夫曼编码生成的代码串,输出相应的电文字符串。?

设计要求:?(1)从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树及哈夫曼编码。?(2)利用已经建好的哈夫曼树,对输入的字符串进行编码,输出编码序列。?(3)利用已建好的哈夫曼树对输入的二进制编码进行译码,并输出结果。??设计任务: ?从键盘输入一串电文字符能输出对应的哈夫曼编码。同时,能翻译由哈夫曼编码生成的代码串,输出相应的电文字符串。?设计要求:?(1)从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树及哈夫曼编码。?(2)利用已经建好的哈夫曼树,对输入的字符串进行编码,输出编码序列。?(3)利用已建好的哈夫曼树对输入的二进制编码进行译码,并输出结果。??

三、实验环境

Vc++

四、实验内容

从键盘输入一串电文字符能输出对应的哈夫曼编码。同时,能翻译由哈夫曼编码生成的代码串,输出相应的电文字符串。?

五、算法描述及实验步骤

一、对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。(为方便在计算机上实现算法,一般还要求以Ti的权值Wi的升序排列。)

二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。?

三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。?

四、重复二和三两步,直到集合F中只有一棵二叉树为止。?

六、调试过程及实验结果

实验七哈夫曼编码

七、总结

通过这次编程使我对哈弗曼编码有了更深刻的理解,并且学会了将之前学过的东西运用到程序中来。

八、源程序

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

typedef char *HuffmanCode; //动态分配数组,存储哈夫曼编码

typedef struct

{

unsigned int weight; //用来存放各个结点的权值

unsigned int parent,LChild,RChild; //指向双亲、孩子结点的指针 } HTNode, *HuffmanTree; //动态分配数组,存储哈夫曼树

//选择两个parent为0,且weight最小的结点s1和s2

void Select(HuffmanTree *ht,int n,int *s1,int *s2)

{

int i,min;

for(i=1; i<=n; i++)

{

if((*ht)[i].parent==0)

{

min=i;

break;

}

}

for(i=1; i<=n; i++)

{

if((*ht)[i].parent==0)

{

if((*ht)[i].weight<(*ht)[min].weight)

min=i;

}

}

*s1=min;

for(i=1; i<=n; i++)

{

if((*ht)[i].parent==0 && i!=(*s1))

{

min=i;

break;

}

}

for(i=1; i<=n; i++)

{

if((*ht)[i].parent==0 && i!=(*s1))

{

if((*ht)[i].weight<(*ht)[min].weight) min=i; }

}

*s2=min;

}

//构造哈夫曼树ht。w存放已知的n个权值

void CrtHuffmanTree(HuffmanTree *ht,int *w,int n) {

int m,i,s1,s2;

m=2*n-1;

*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); for(i=1; i<=n; i++) //1--n号存放叶子结点,初始化 {

(*ht)[i].weight=w[i];

(*ht)[i].LChild=0;

(*ht)[i].parent=0;

(*ht)[i].RChild=0;

}

for(i=n+1; i<=m; i++)

{

(*ht)[i].weight=0;

(*ht)[i].LChild=0;

(*ht)[i].parent=0;

(*ht)[i].RChild=0;

} //非叶子结点初始化

printf("\nHuffmanTree: \n");

for(i=n+1; i<=m; i++) //创建非叶子结点,建哈夫曼树

{ //在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0

//且weight最小的结点,其序号分别赋值给s1、s2

Select(ht,i-1,&s1,&s2);

(*ht)[s1].parent=i;

(*ht)[s2].parent=i;

(*ht)[i].LChild=s1;

(*ht)[i].RChild=s2;

(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;

printf("%d (%d, %d)\n",(*ht)[i].weight,(*ht)[s1].weight,(*ht)[s2].weight); }

printf("\n");

} //哈夫曼树建立完毕

//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码

void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)

{

char *cd;

int i,start,p;

unsigned int c;

hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); //分配n个编码的头指针

cd=(char *)malloc(n*sizeof(char)); //分配求当前编码的工作空间

cd[n-1]='\0'; //从右向左逐位存放编码,首先存放编码结束符

for(i=1; i<=n; i++) //求n个叶子结点对应的哈夫曼编码

{

start=n-1; //初始化编码起始指针

for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) //从叶子到根结点求编码

if( (*ht)[p].LChild==c) cd[--start]='0'; //左分支标0

else cd[--start]='1'; //右分支标1

hc[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个编码分配空间 strcpy(hc[i],&cd[start]);

}

free(cd);

for(i=1; i<=n; i++)

printf("HuffmanCode of %3d is %s\n",(*ht)[i].weight,hc[i]); printf("\n");

}

void main()

{

HuffmanTree HT;

HuffmanCode HC;

int *w,i,n,wei,m;

printf("\nn = " );

scanf("%d",&n);

w=(int *)malloc((n+1)*sizeof(int));

printf("\ninput the %d element's weight:\n",n);

for(i=1; i<=n; i++)

{

printf("%d: ",i);

fflush(stdin);

scanf("%d",&wei);

w[i]=wei;

}

CrtHuffmanTree(&HT,w,n);

CrtHuffmanCode(&HT,&HC,n);

}

更多相关推荐:
哈夫曼编码实验报告

哈夫曼编码器实验报告学院:计算机学院班级:计科0801班姓名:***学号:***一.实验目的练习树和哈夫曼树的有关操作,和各个算法程序,理解哈夫曼树的编码和译码二.实验环境Microsoftvisualc++三…

C语言-哈夫曼编码实验报告

福建工程学院课程设计课程数据结构题目哈夫曼编码和译码专业信息管理信息系统班级座号15号姓名林左权20xx年6月27日1实验题目哈夫曼编码和译码一要解决的问题利用哈夫曼编码进行信息通信可以大大提高信道利用率缩短信...

哈夫曼编码实验报告

数据结构作业报告哈夫曼编码实验报告姓名班级学号摘要本程序能执行让一段字符以哈夫曼编码的形式被转存或将一段哈夫曼编码翻译成字符通过字符的频率统计哈夫曼树的建立递归求字符的哈夫曼编码完成这个程序让我熟悉哈夫曼编码的...

哈夫曼编码实验报告

中南大学数据结构课程姓名刘阳班级信息0703学号0903070312实验时间081114指导老师赵颖

哈夫曼编码实验报告

北京邮电大学信息与通信工程学院数据结构实验报告实验名称实验三哈夫曼编码学生姓名牛佳宁班级20xx211107班内序号27学号10210213日期20xx年12月10日1实验要求利用二叉树结构实现赫夫曼编解码器1...

数据结构+哈夫曼编码+实验报告

实验报告一实验目的掌握哈夫曼树及其应用二实验内容利用哈夫曼算法构造最优二叉树然后对构造好的二叉树的叶子结点进行前缀编码三实验步骤1审清题意分析并理出解决问题的基本思路2根据基本思路设计好程序的算法3根据算法编写...

哈夫曼编码实验报告

数据结构实验班级软件C092姓名孙琼芳学号098586一实验目的利用哈夫曼编码进行通信可以大大提高信道利用率缩短信息传输时间降低传输成本但是这要求在发送端通过一个编码系统对待传数据预先编码在接收端将传来的数据进...

数据结构试验报告霍夫曼编码

数据结构实验报告三学院自动化学院学号姓名日期20xx1209实验目的1掌握哈夫曼编码原理2熟练掌握哈夫曼树的生成方法3理解数据编码压缩和译码输出编码的实现4掌握二叉树的基本3操作实验内容利用哈夫曼编码进行通信可...

数据结构实验三哈夫曼编码

数据结构实验报告实验名称实验3哈夫曼树学生姓名XXX班级班内序号学号日期20xx年12月1日1实验要求实验目的通过选择下面两个题目之一进行实现掌握如下内容掌握二叉树基本操作的实现方法了解赫夫曼树的思想和相关概念...

哈夫曼编码课程设计报告

数据结构课程设计报告课题专业班级学号姓名指导教师1课程设计的目的和意义在当今信息爆炸时代如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视哈夫曼编码正是一种应用广泛且...

Huffman编码实验报告

1二进制哈夫曼编码的原理及步骤(1)信源编码的计算设有N个码元组成的离散、无记忆符号集,其中每个符号由一个二进制码字表示,信源符号个数n、信源的概率分布P={p(si)},i=1,..,n。且各符号xi的以li…

编码理论实验报告实验一霍夫曼编码中信息熵及编码效率的实验

实验名称实验一霍夫曼编码中信息熵及编码效率的实验一实验目的1掌握霍夫曼编码中信息熵的定义性质和计算2掌握霍夫曼编码中平均码字长度的定义和计算3掌握霍夫曼编码中编码效率的定义和计算4正确使用C语言实现霍夫曼编码中...

哈夫曼编码实验报告(37篇)