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字节表示时的总字节数, 以及最小的 ...
随机推荐
- Hibernate--(二)增删改查
1.增删改查: public class Test { public static void main(String[] args) { SessionFactory sf = new Configu ...
- git提交时设置忽略部分文件提交
git当前提交项目时总是会提交很多东西把Debug文件也提交了 在项目根目录(例如我的项目文件夹下,.sln文件的上一级目录)下建一个.gitignore文件,文件内容直接可粘贴下面的,这样 pack ...
- HDU 1226 超级密码(BFS) (还需研究)
Time Limit:10000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Desc ...
- 吴裕雄--天生自然TensorFlow2教程:张量排序
import tensorflow as tf a = tf.random.shuffle(tf.range(5)) a tf.sort(a, direction='DESCENDING') # 返回 ...
- 使用docker-sync解决docker for mac 启动的虚拟容器程序运行缓慢的问题
背景: 新入职的公司有个非常OG的大项目,为了避免新同学重复造轮子,有哥们已经把项目需要的所有打好了一个镜像供我们启动docker. 初次启动docker 使用的命令如下: docker run -i ...
- 尝试用kotlin做一个app(二)
导航条 我想实现的效果是这样的 类似于ViewPager的效果,子类导航页面可以滑动,当滑动某个子类导航页面,导航线会平滑地向父类导航移动 ·添加布局 <!--导航分类:编程语言/技术文档/源码 ...
- 基于磁盘的Kafka为什么这么快
专注于Java领域优质技术,欢迎关注 作者: Wyman 大数据手稿笔记 Kafka是大数据领域无处不在的消息中间件,目前广泛使用在企业内部的实时数据管道,并帮助企业构建自己的流计算应用程序.Kafk ...
- eclipse上部署到tomcat不能自动部署maven管理的额jar包
- 吴裕雄--天生自然MySQL学习笔记:MySQL 序列使用
MySQL 序列是一组整数:1, 2, 3, ...,由于一张数据表只能有一个字段自增主键, 如果你想实现其他字段也实现自动增加,就可以使用MySQL序列来实现. 使用 AUTO_INCREMENT ...
- one_day_one_linuxCmd---sz命令
<坚持每天学习一个 linux 命令,今天我们来学习 sz && rz 命令> 前言:我们一般通过 ssh 客户端来进行远程登录和管理的,windows主机使用 ssh 登 ...