Huffman编码实验
一、 实验目的
熟练掌握哈夫曼树的建立和哈夫曼编码的算法实现。
二、 实验内容
根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求赫夫曼编码,并能把给定的编码进行译码。
三、 实验要求
(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编码实验的更多相关文章
- Jcompress: 一款基于huffman编码和最小堆的压缩、解压缩小程序
前言 最近基于huffman编码和最小堆排序算法实现了一个压缩.解压缩的小程序.其源代码已经上传到github上面: Jcompress下载地址 .在本人的github上面有一个叫Utility的re ...
- [老文章搬家] 关于 Huffman 编码
按:去年接手一个项目,涉及到一个一个叫做Mxpeg的非主流视频编码格式,编解码器是厂商以源代码形式提供的,但是可能代码写的不算健壮,以至于我们tcp直连设备很正常,但是经过一个UDP数据分发服务器之后 ...
- Huffman编码
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <cstri ...
- 【数据压缩】Huffman编码
1. 压缩编码概述 数据压缩在日常生活极为常见,平常所用到jpg.mp3均采用数据压缩(采用Huffman编码)以减少占用空间.编码\(C\)是指从字符空间\(A\)到码字表\(X\)的映射.数据压缩 ...
- 优先队列求解Huffman编码 c++
优先队列小析 优先队列的模板: template <class T, class Container = vector<T>,class Compare = less< ...
- Huffman编码实现电文的转码与译码
//first thing:thanks to my teacher---chenrong Dalian Maritime university /* 构造Huffman Tree思路: ( ...
- huffman 编码
huffman压缩是一种压缩算法,其中经典的部分就是根据字符出现的频率建立huffman树,然后根据huffman树的构建结果标示每个字符.huffman编码也称为前缀编码,就是每个字符的表示形式不是 ...
- 基于二叉树和数组实现限制长度的最优Huffman编码
具体介绍详见上篇博客:基于二叉树和双向链表实现限制长度的最优Huffman编码 基于数组和基于链表的实现方式在效率上有明显区别: 编码256个符号,符号权重为1...256,限制长度为16,循环编码1 ...
- uvalive 2088 - Entropy(huffman编码)
题目连接:2088 - Entropy 题目大意:给出一个字符串, 包括A~Z和_, 现在要根据字符出现的频率为他们进行编码,要求编码后字节最小, 然后输出字符均为8字节表示时的总字节数, 以及最小的 ...
随机推荐
- TX2开发板Ubuntu16.04安装中文输入法
打开终端输入安装输入法: sudo apt-get install fcitx fcitx-googlepinyin fcitx-module-cloudpinyin fcitx-sunpinyin ...
- 量化投资_Multicharts数组操作函数_zeros()设定数组元素为0(自定义)
1. 函数的用法类似于Python的zeros函数,给定数组尺寸,让数组的元素归零 //zeros:根据设定的尺寸长度,让一维数组的元素全部归零 inputs: arr[MaxSize]( numer ...
- Java平台上的AOP实现机制
Java平台上的AOP实现机制 动态代理(Dynamic Proxy)机制,在运行期间动态的为相应接口生成对应的代理对象.SpringAop默认情况下采用这种机制来实现AOP机能.缺点:相对于编译后的 ...
- 实验吧Web-难-貌似有点难(http头欺骗)
有关一些http头,参考:https://blog.csdn.net/zz_Caleb/article/details/84147066 打开链接:点击view source看到一段代码 <?p ...
- Android自定义View——刮刮卡效果
想要红包的实现效果的可以关注我的博客,仿饿了么红包 下层图片:我们的红包的图片 上层图片:有两部分 一部分是灰色背景 一部分是拥有透明度为0,并且模式为交集的画笔 使用滑动监听,滑动时,用透明度为0的 ...
- shell教程<入门篇>
由于我平时的工作环境是linux,所以无可避免的经常使用命令行模式和shell脚本,而且有些命令行每天都要输好多遍,比如ssh登录之类的,所以干脆把平时常用的命令都写成脚本文件,所以特意开了一个she ...
- QMainWindow的空间布局结构
简单讲一下Qt的QMainWindow的结构,Qt的顶级窗口有三种类型,首先是万恶之源(...应该说是大部分控件的父类...)的QWidget,然后是QMainWidget和QDialog,后面两者也 ...
- SSM框架和微服务构架和的联系与区别
spring和springMvc: 1. spring是一个一站式的轻量级的java开发框架,核心是控制反转(IOC)和面向切面(AOP),针对于开发的WEB层(springMvc).业务层(Ioc) ...
- UVALive 3704 细胞自动机 矩阵快速幂
是时候要做做数学类的题目了 这属于比较简单的矩阵快速幂了,因为有个已知的矩阵循环的结论,所以为了节约时空,只需要保留一行即可,这个稍微有点难写,也不是难写,主要是注意细节.其他的矩阵快速幂一下即可 # ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL 插入数据
MySQL 表中使用 INSERT INTO SQL语句来插入数据. 可以通过 mysql> 命令提示窗口中向数据表中插入数据,或者通过PHP脚本来插入数据. 以下为向MySQL数据表插入数据通 ...