一、 实验目的

熟练掌握哈夫曼树的建立和哈夫曼编码的算法实现。

二、 实验内容

根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求赫夫曼编码,并能把给定的编码进行译码。

三、 实验要求

(1)初始化:从键盘输入一字符串(或读入一文件),统计出现的字符和每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树。对各个字符进行哈夫曼编码,最后打印输出字符及每个字符对应的哈夫曼编码。

(2)编码:利用已建好的哈夫曼树对“输入串”进行哈夫曼编码,最后打印输入串对应的哈夫曼编码(写入文件)。

(3)计算压缩比(选作)

(4)译码:利用已建好的哈夫曼树对给定的一串代码进行译码,并打印输出得到的字符串。(选作)

测试数据:对字符串{casbcatbsatbat}进行编码;对电文“1101000”译码。字符集D={   ?},出现频率为w={?}

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const int maxn=1e4+;
using namespace std; struct node
{
int val;//权值
int lc;//左孩子
int rc;//右孩子
int parent;//双亲
char c;//节点字符
int flag;//标志
}Huffman_Tree[*]; int num[]={};//每种字符的个数
char Huffman_code[][];//每种字符对应的编码
char str[maxn];//原字符串
int cnt;//Huffman树节点个数计数器 void Init()//初始化
{
printf("请输入一串字符串(该字符串只能为小写字母):\n");
gets(str);
for(int i=;str[i];i++)
{
num[str[i]-'a']++;
}
int sum=;
for(int i=;i<;i++)
{
if(num[i])//初始化
{
sum++;
Huffman_Tree[++cnt].c=i+'a';
Huffman_Tree[cnt].val=num[i];
Huffman_Tree[cnt].lc=;
Huffman_Tree[cnt].rc=;
Huffman_Tree[cnt].parent=;
Huffman_Tree[cnt].flag=;
}
}
for(int k=;k<sum-;k++)//建树
{
int MIN1=INF;
int MIN2=INF;
int Index1,Index2;
for(int i=;i<=cnt;i++)
{
if(Huffman_Tree[i].flag==)
{
if(Huffman_Tree[i].val<MIN1)
{
MIN2=MIN1;
Index2=Index1;
MIN1=Huffman_Tree[i].val;
Index1=i;
}
else if(Huffman_Tree[i].val<MIN2)
{
MIN2=Huffman_Tree[i].val;
Index2=i;
}
}
}
Huffman_Tree[Index1].flag=;
Huffman_Tree[Index2].flag=;
int t=MIN1+MIN2;
Huffman_Tree[++cnt].val=t;
Huffman_Tree[cnt].c='*';
Huffman_Tree[cnt].lc=Index1;
Huffman_Tree[cnt].rc=Index2;
Huffman_Tree[cnt].parent=;
Huffman_Tree[cnt].flag=;
Huffman_Tree[Index1].parent=cnt;
Huffman_Tree[Index2].parent=cnt;
}
for(int i=;i<;i++)//求Huffman编码
{
if(num[i])
{
char tem[];
int len=;
int p;
for(int j=;j<=cnt;j++)
{
if(Huffman_Tree[j].c==i+'a')
{
p=j;
break;
}
}
while(Huffman_Tree[p].parent)
{
if(Huffman_Tree[Huffman_Tree[p].parent].lc==p)
tem[len++]='';
else
tem[len++]='';
p=Huffman_Tree[p].parent;
}
tem[len]='\0';
int ccnt=;
for(int j=len-;j>=;j--)
{
Huffman_code[i][ccnt++]=tem[j];
}
Huffman_code[i][ccnt]='\0';
// for(int j=0;j<len/2;j++)
// {
// char t=tem[j];
// tem[j]=tem[len-1-j];
// tem[len-1-j]=t;
// }
// NUM[i]=tem;
// puts(NUM[i]);
}
}
printf("每个字母对应的Huffman编码为:\n");
for(int i=;i<;i++)
{
if(num[i])
{
printf("%c:",i+'a');
puts(Huffman_code[i]);
}
}
} void Print_out()//编码
{
printf("输入串对应的哈夫曼编码为:\n");
for(int i=;str[i];i++)//根据字符匹配编码
{
printf("%s",Huffman_code[str[i]-'a']);
}
printf("\n");
} void Solve1()//计算压缩比
{
int sum=;//字符种类个数
for(int i=;i<;i++)
{
if(num[i])
sum++;
}
double a=;//平均码长
int b;//等长码
if(sum==)
b=;
else b=(int)log2(sum-)+;
double ans;
for(int i=;i<;i++)
{
if(num[i])
{
a+=(num[i]*1.0/strlen(str))*strlen(Huffman_code[i]);
}
}
ans=a/b*1.0;
printf("该字符串压缩比为:\n");
printf("%.2lf%%\n",ans*);
} void Solve2()//译码
{
char tem[maxn];
// char ans[maxn];
// int len=0;
printf("请输入要进行译码的0-1串:\n");
scanf("%s",tem);
// int i,j,k;
// for(i=0;tem[i];i++)
// {
// for(k=0;k<26;k++)
// {
// if(num[k])
// {
// for(j=0;j<strlen(Huffman_code[k]);)
// {
// if(tem[i]==Huffman_code[k][j])
// {
// i++;
// j++;
// }
// else
// {
// i-=j;
// j=0;
// break;
// }
// }
// if(j==strlen(Huffman_code[k]))
// {
// i--;
// ans[len++]=k+'a';
// break;
// }
// }
// }
// }
// ans[len]='\0';
// printf("该0-1串译文为:\n");
// puts(ans);
int rt;//Huffman树根
for(int i=;i<=cnt;i++)//找到根
{
if(Huffman_Tree[i].parent==)
{
rt=i;
break;
}
}
for(int i=;tem[i];i++)//类似于字典树匹配
{
for(int p=rt;;i++)
{
if(tem[i]=='')
p=Huffman_Tree[p].lc;
else
p=Huffman_Tree[p].rc;
if(Huffman_Tree[p].c!='*')
{
printf("%c",Huffman_Tree[p].c);
break;
}
}
}
printf("\n");
} int main()
{
Init();
printf("--------------------------------\n");
Print_out();
printf("--------------------------------\n");
Solve1();
printf("--------------------------------\n");
Solve2();
printf("--------------------------------\n");
return ;
}

Huffman编码实验的更多相关文章

  1. Jcompress: 一款基于huffman编码和最小堆的压缩、解压缩小程序

    前言 最近基于huffman编码和最小堆排序算法实现了一个压缩.解压缩的小程序.其源代码已经上传到github上面: Jcompress下载地址 .在本人的github上面有一个叫Utility的re ...

  2. [老文章搬家] 关于 Huffman 编码

    按:去年接手一个项目,涉及到一个一个叫做Mxpeg的非主流视频编码格式,编解码器是厂商以源代码形式提供的,但是可能代码写的不算健壮,以至于我们tcp直连设备很正常,但是经过一个UDP数据分发服务器之后 ...

  3. Huffman编码

    #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <cstri ...

  4. 【数据压缩】Huffman编码

    1. 压缩编码概述 数据压缩在日常生活极为常见,平常所用到jpg.mp3均采用数据压缩(采用Huffman编码)以减少占用空间.编码\(C\)是指从字符空间\(A\)到码字表\(X\)的映射.数据压缩 ...

  5. 优先队列求解Huffman编码 c++

    优先队列小析      优先队列的模板: template <class T, class Container = vector<T>,class Compare = less< ...

  6. Huffman编码实现电文的转码与译码

    //first thing:thanks to my teacher---chenrong      Dalian Maritime university /* 构造Huffman Tree思路: ( ...

  7. huffman 编码

    huffman压缩是一种压缩算法,其中经典的部分就是根据字符出现的频率建立huffman树,然后根据huffman树的构建结果标示每个字符.huffman编码也称为前缀编码,就是每个字符的表示形式不是 ...

  8. 基于二叉树和数组实现限制长度的最优Huffman编码

    具体介绍详见上篇博客:基于二叉树和双向链表实现限制长度的最优Huffman编码 基于数组和基于链表的实现方式在效率上有明显区别: 编码256个符号,符号权重为1...256,限制长度为16,循环编码1 ...

  9. uvalive 2088 - Entropy(huffman编码)

    题目连接:2088 - Entropy 题目大意:给出一个字符串, 包括A~Z和_, 现在要根据字符出现的频率为他们进行编码,要求编码后字节最小, 然后输出字符均为8字节表示时的总字节数, 以及最小的 ...

随机推荐

  1. EUI库 - 9 - 数据集合 - 数组集合

      ArrayCollection  当数组内的数据被修改了(增删改),组件能有效的获知 myCollection.addEventListener(eui.CollectionEvent.COLLE ...

  2. unique constraint(PD.HSI_RIGHT) violated

    插入时报错,原因:唯一约束重复了.... 查看表中有唯一约束的列是不是已经有值了 果然,唯一约束有两条重复的记录. ------------------------------------------ ...

  3. BZOJ:2190: [SDOI2008]仪仗队

    题解:欧拉函数 #include<iostream> #include<cstdio> #include<cstring> using namespace std; ...

  4. docker - how do you disable auto-restart on a container?

    https://stackoverflow.com/questions/37599128/docker-how-do-you-disable-auto-restart-on-a-container 9 ...

  5. Codeforces 444C 线段树 懒惰标记

    前天晚上的CF比赛div2的E题,很明显一个线段树,当时还在犹豫复杂度的问题,因为他是区间修改和区间查询,肯定是要用到懒惰标记. 然后昨天真的是给这道题跪了,写了好久好久,...我本来是写了个add标 ...

  6. jar包-循环遍历-开机启动服务-微服务-多项目拷贝-pid杀死进程-mysql备份脚本-防火墙检测脚本

    vi /root/serverkaiji.sh #!/bin/bash ls /tlvnksc/ | egrep -v "^c|^f" > /root/service.lis ...

  7. pyCharm中设置查看运行过程中的变量实时情况

    1.点击运行栏的这个灰色向下剪头: 2.单击“Edit Configurations”, 3.在出现的窗口上,勾选上:“Show command line afterwards” 或 “run wit ...

  8. spring boot 环境配置(profile)切换

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  9. 尝试用kotlin做一个app(四)

    本来是应该为主页加载数据库数据了,但是想着做后台,之前写jsp后台写吐了,所以先拖几天.把之前的代码完善一下,或者添加些新内容. ...... 多个fragment切换卡顿 首先修正一个bug.从主页 ...

  10. idea 2019.3 最新破解补丁和激活码,可破解至2089年!

    链接:https://blog.csdn.net/qq_42914528/article/details/85617901 上面方法失效了,请尝试以下方式激活(2020.1.6更新) idea激活码( ...