算法分析与设计 实验二 哈夫曼编码

时间:2024.4.20

昆明理工大学信息工程与自动化学院学生实验报告

201     201   学年    学期

课程名称:算法设计与分析       开课实验室:               年    月   日

一、上机目的及内容

1.上机内容

设需要编码的字符集为{d1, d2, …, dn},它们出现的频率为{w1, w2, …, wn},应用哈夫曼树构造最短的不等长编码方案。

2.上机目的

(1)了解前缀编码的概念,理解数据压缩的基本方法;

(2)掌握最优子结构性质的证明方法;

(3)掌握贪心法的设计思想并能熟练运用。

二、实验原理及基本技术路线图(方框原理图或程序流程图)

(1)证明哈夫曼树满足最优子结构性质;

(2)设计贪心算法求解哈夫曼编码方案;

(3)设计测试数据,写出程序文档。

数据结构与算法:

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

typedef struct

{

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

  unsigned int parent,LChild,RChild;  //指向双亲、孩子结点的指针

} HTNode, *HuffmanTree;  //动态分配数组,存储哈夫曼树

程序流程图:

 

三、所用仪器、材料(设备名称、型号、规格等或使用软件)

1台PC及VISUAL C++6.0软件

四、实验方法、步骤(或:程序代码或操作过程) 

程序代码:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

typedef struct

{

  unsigned int weight; 

  unsigned int parent,LChild,RChild; 

} HTNode, *HuffmanTree;  //动态分配数组,存储哈夫曼树

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

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("\n所构造的哈夫曼树为: \n");

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

 {

  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 a[100];

 int i,start,p,w=0;

 unsigned int c;

 hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); 

 cd=(char *)malloc(n*sizeof(char));

 cd[n-1]='\0';

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

 {

  a[i]=0;

  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]='1'; 

              a[i]++;

       }

    else

       {

              cd[--start]='0'; 

              a[i]++;

       }

  }

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

  strcpy(hc[i],&cd[start]);   

 }

 free(cd);

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

   printf("权值为%d的哈夫曼编码为:%s\n",(*ht)[i].weight,hc[i]);

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

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

 printf("\n带权路径长度WPL为:%d\n\n",w);

}

void main()

{

 HuffmanTree HT;

 HuffmanCode HC;

 int *w,i,n,wei;

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

 printf("请输入结点个数:" );

 scanf("%d",&n);

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

 printf("\n请分别输入这%d个结点的权值:\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);

}

五、实验过程原始记录( 测试数据、图表、计算等)

 

六、实验结果、分析和结论(误差分析与数据处理、成果总结等。其中,绘制曲线图时必须用计算纸或程序运行结果、改进、收获)

这次实验的内容是哈夫曼编码,哈夫曼树也就是最优二叉树,构造哈夫曼树的过程就是先在所有结点中找到权值最小的两个结点合并,依次这样找到较小的结点合并,最终生成哈夫曼树。树中所有叶子结点的带权路径长度之和最小,带权路径长度就是该结点到树根之间的路径长度与结点上权的乘积,且权值越大的叶子离跟越近。


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


算法设计与分析实验报告

姓名:杨勇涛

班级:计科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);

}

更多相关推荐:
算法设计与分析实验报告1

攀枝花学院实验报告实验名称算法设计与分析课程实验实验内容比较排序算法的效率实验日期20xx0326院系数学与计算机姓名吴永昊学号20xx10804043同组人指导老师银星成绩一目的与任务通过算法的程序实现和执行...

算法设计与分析实验报告

算法设计与分析课程报告课题名称算法设计与分析课题负责人名学号同组成员名单角色指导教师评阅成绩评阅意见提交报告时间20xx年6月12日第二章递归与分治策略23改写二分搜索算法1问题描述设a0n1是已排好序的数组请...

计算机算法与设计分析实验报告

计算机算法与设计分析实验报告班级姓名学号目录实验一分治与递归11基本递归算法12棋盘覆盖问题23二分搜索34实验小结5实验二动态规划算法51最长公共子序列问题52最大子段和问题73实验小结8实验三贪心算法81多...

算法设计与分析实验报告格式

算法设计与分析实验报告一实验名称统计数字问题评分实验日期年月日指导教师刘长松姓名刘飞初专业班级计算机0901学号10一实验要求1掌握算法的计算复杂性概念2掌握算法渐近复杂性的数学表述3掌握用C语言描述算法的方法...

算法设计与分析实验报告

算法分析与设计实验报告实验报告题目实验一递归与分治策略一实验目的1加深学生对分治法算法设计方法的基本思想基本步骤基本方法的理解与掌握2提高学生利用课堂所学知识解决实际问题的能力3提高学生综合应用所学知识解决实际...

算法设计与分析实验报告格式

算法设计与分析实验报告班级姓名学号20xx年11月18日目录实验一二分查找程序实现01页实验二棋盘覆盖问题04页实验三01背包问题的动态规划算法设计07页实验四背包问题的贪心算法10页指导教师对实验报告的评语成...

算法设计与分析试验报告

武汉理工大学学生实验报告书实验课程名称算法设计与分析开课学院计算机科学与技术学院指导老师姓名何九周学生姓名王鹏学生专业班级软件100420xx20xx学年第1学期实验课程名称算法设计与分析intmiddleif...

终稿- -算法设计与分析实验报告格式 3

算法设计与分析实验报告一实验名称统计数字问题评分实验日期年月日指导教师姓名专业班级学号20xx1一实验要求1掌握算法的计算复杂性概念2掌握算法渐近复杂性的数学表述3掌握用C语言描述算法的方法4实现具体的编程与上...

-算法设计与分析实验报告格式 2

算法设计与分析实验报告一实验名称统计数字问题评分实验日期年月日指导教师刘长松姓名兜兜专业班级计算机10学号20xx一实验要求1掌握算法的计算复杂性概念2掌握算法渐近复杂性的数学表述3掌握用C语言描述算法的方法4...

算法分析实验报告

实验一最大公约数问题用连续整除法求最大公约数includeltstdiohgtintgcdintmintnintminifngtmminmelseminnforminnmingt1minifmmin0ampam...

算法设计与分析实验报告

算法设计与分析实验报告指导老师沙莎学院信息科学与工程学院班级计科0508姓名戚婕学号10完成日期20xx年12月目录实验一分治法211实验要求212实验内容213核心算法214程序代码415实验结果8实验二21...

算法设计与分析的实验报告

实验一递归与分治策略一实验目的1加深学生对分治法算法设计方法的基本思想基本步骤基本方法的理解与掌握2提高学生利用课堂所学知识解决实际问题的能力3提高学生综合应用所学知识解决实际问题的能力二实验内容1设a0n1是...

算法设计与分析实验报告(40篇)