数据结构——哈弗曼编码问题

实验六 基于哈夫曼树的数据压缩算法
【实验目的】

  1. 掌握哈夫曼树的构造算法。
  2. 掌握哈夫曼编码的构造算法。
    【实验内容】
    问题描述
    输入一串字符,根据给定的字符串中字符出现的频率建立相应的哈夫曼树,
    构造哈夫曼编码表,在此基础上可以对压缩文件进行压缩(即编码),同时可以对
    压缩后的二进制编码文件进行解压(即译码)。
    输入要求
    多组数据,每组数据 1 行,为一个字符串(只考虑 26 个小写字母即可)。当输
    入字符串为“00”时,输入结束。
    输出要求
    每组数据输出 2n+3 行(n 为输入串中字符类别的个数)。第 1 行为统计出来
    的字符出现频率(只输出存在的字符,格式为字符:频度),每两组字符之间用一个
    空格分隔,字符按照 ASCII 码从小到大的顺序排列。第 2 行至第 2n 行为哈夫曼树
    的存储结构的终态(参照实验提示表 5.2,一行当中的数据用空格分隔)。第 2n+1
    行为每个字符的哈夫曼编码(只输出存在的字符,格式为字符:编码),每两组字符
    之间用一个空格分隔,字符按照 ASCII 码从小到大的顺序排列。第 2n+2 行为编码
    后的字符串,第 2n+3 行为解码后的字符串(与输入的字符串相同)。
    输入样例
    aaaaaaabbbbbccdddd
    aaccb
    00
    输出样例
    a:7 b:5 c2 d:4
    1 7 7 0 0
    2 5 6 0 0
    3 2 5 0 0
    4 4 5 0 0
    5 6 6 3 4
    6 1 1 7 2 5
    7 1 8 0 1 6
    a:0 b:10 c:110 d:111
    00000001010101011011011111
    aaaaaaabbbbbccdddd
    a:2 b:1 c:3
    1 2 4 0 0
    2 1 4 0 0
    3 3 5 0 0
    4 3 5 2 1
    5 6 0 3 4
    a:11 b:10 c:0
    111110000
    aabccc
    【实验提示】
    首先,读入一行字符串,统计每个字符出现的频率;然后,根据字符出现的频
    率利用提示算法 1 建立相应的哈夫曼树;最后,根据得到的哈夫曼树利用算法 2
    求出每个字符的哈夫曼编码。

思路:

  1. 该问题使用顺序表来存储哈夫曼树

  2. char_statiscal()函数统计每种字符出现的次数

  3. CreatHuffmanCode()构建哈弗曼树数组,共有n个叶子结点,n-1个非叶子结点。

  4. select()函数选取哈弗曼数组中权值最小的两个叶子结点,返回到CreatHuffmanCode()函数中,用于完成对非叶子结点的构建
    并且同时修改叶子结点的父亲结点,和非叶子结点的孩子结点

  5. 结构体
    typedef struct
    {
    char info;//存储每一个结点对应的字符
    int weight;//权值
    int parent,lchild,rchild;
    int index;//存储每一个结点对应的下标
    char code[MAXCODE];//存储每一个字符对应的二进制编码

}HTNode,*HuffmanTree;

6.CreatHuffmanCode()函数为每种字符创建各自的二进制编码

  1. encode()将每个字符的编码放到该叶子结点的code[]
    中去。
    具体过程:依次读入字符,在哈弗曼编码表(数组中)找到次字符,将字符转换为编码表中存放的编码串。

  2. decode()利用以构建好的哈弗曼树来进行解码
    对编码后的文件进行译码的过程必须借助于哈弗曼树。
    具体过程:依次读入文件的二进制码,从哈弗曼树的根节点出发,若是0,则走向左子树,否则走向右子树。一旦到达叶子结点,便译出相应的字符编码。然后继续从根节点出发继续译码,直到全部结束。

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
#define MAXSTRLEN 255
#define MAXCODE 20char alphabet[26]={0};
char alphabet2[26];
typedef char **HuffmanCode;
typedef struct
{char String[MAXSTRLEN]; 
}SqString;typedef struct
{char info;//存储每一个结点对应的字符 int weight;//权值 int parent,lchild,rchild;int index;//存储每一个结点对应的下标 char code[MAXCODE];//存储每一个字符对应的二进制编码 }HTNode,*HuffmanTree;//统计字符串中每种字符出现的次数 
void char_statiscal(SqString &S,char *alphabet,int &num,char *alphabet2)
{int i=0,j=0;for(i=0;S.String[i]!='\0';i++){if(S.String[i]>='a'&&S.String[i]<='z')alphabet[S.String[i]-'a']++;}for(int j=0;j<26;j++){if(alphabet[j]>0){printf("%c:%d  ",'a'+j,alphabet[j]);num++;}}printf("\n"); int x=0;for(int j=0;j<26;j++){if(alphabet[j]>0){alphabet2[x]='a'+j;x++;}}}//创建一个简单的哈弗曼树用于复制一个复杂的哈弗曼树  主要用于排序了 
void createHuffmanTree2(HuffmanTree &HT,int n,char *alphabet,char*alphabet2)
{if(n<1)return ;int m=2*n-1;int number=0;HT=new HTNode[m+1];for(int i=1;i<=n;i++){HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;HT[i].index=i;}for(int j=0;j<26;j++){if(alphabet[j]>0)HT[++number].weight=0;}}//HT哈夫曼树,ht,是用于存储排序后的哈夫曼树,n是所要排序的哈夫曼树的节点个数
void select(HuffmanTree &HT,int length,int &s1,int &s2)
{ HuffmanTree ht;createHuffmanTree2(ht,length,alphabet,alphabet2);for(int i=1;i<=length;i++){{	ht[i].weight=HT[i].weight;ht[i].index=HT[i].index;}}int temp_index=0;int temp_weight=0;for(int i=1;i<length;i++){for(int j=1;j<=length-i;j++){if(ht[j].weight>ht[j+1].weight){temp_weight=ht[j].weight;ht[j].weight=ht[j+1].weight;ht[j+1].weight=temp_weight;temp_index=ht[j].index;ht[j].index=ht[j+1].index;ht[j+1].index=temp_index;}}}for(int i=1;i<=length;i++){if(HT[ht[i].index].parent==0){s1=ht[i].index;HT[ht[i].index].parent=length+1;break;}}for(int j=1;j<=length;j++){if(HT[ht[j].index].parent==0){s2=ht[j].index;HT[ht[j].index].parent=length+1;break;}}}//构建一颗完整的哈夫曼树 
void createHuffmanTree(HuffmanTree &HT,int n,char *alphabet)
{
//----------------------------创建哈夫曼树---------------------// if(n<1)return ;int m=2*n-1;int number=0;HT=new HTNode[m+1];//构造哈夫曼树节点 的结构体数组,0号单元不占用,其中共有n个叶子节点,n-1个非叶子节点;for(int i=1;i<=m;i++){HT[i].info=alphabet2[i-1];HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;HT[i].index=i;}for(int j=0;j<26;j++){if(alphabet[j]>0)HT[++number].weight=alphabet[j];}
//---------------------------------初始化--------------------------------//int a,b;for(int i=n+1;i<=m;i++){select(HT,i-1,a,b);HT[a].parent=i;HT[b].parent=i;HT[i].lchild=a;HT[i].rchild=b;HT[i].weight=HT[a].weight+HT[b].weight;}for(int a=1;a<=2*n-1;a++){printf("下标为%d的权为 %d 父亲节点:%d,左孩子:%d,右孩子:%d\n",HT[a].index,HT[a].weight,HT[a].parent,HT[a].lchild,HT[a].rchild);}}//为每一个字符创建好各自的二进制编码 
void CreatHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)
{HC=new char*[n+1];char *cd;cd=new char[n];cd[n-1]='\0';int start;int c;int f;for(int i=1;i<=n;i++){start=n-1;c=i,f=HT[i].parent;while(f!=0){--start;if(HT[f].lchild==c)cd[start]='0';else cd[start]='1';c=f,f=HT[f].parent;}HC[i]=new char[n-start];strcpy(HC[i],&cd[start]);}delete cd;for(int i=1;i<=n;i++)printf("%c:%s  ",alphabet2[i-1],HC[i]);printf("\n");	
}//为字符串进行编码 
void encode(SqString &S,HuffmanCode HC,int n,HuffmanTree HT,char *sum)
{for(int i=0;S.String[i]!='\0';i++){for(int j=1;j<=n;j++){if(S.String[i]==HT[j].info){strcat(sum,HC[j]);strcpy(HT[j].code,HC[j]);break;}}}printf("%s\n",sum);
}//对已经编码好的字符串进行解码 
void decode(char *sum,int n,HuffmanTree HT)
{int index=2*n-1;//根节点开始 int j=0;while(sum[j]!='\0'){if(sum[j]=='0')index=HT[index].lchild;else index=HT[index].rchild;if(HT[index].lchild==0&&HT[index].rchild==0){printf("%c",HT[index].info);index=2*n-1;}j++;}}int main()
{SqString S;do{gets(S.String);HuffmanTree HT;char sum[100]={""};int num=0;char alphabet[26]={0};char_statiscal(S,alphabet,num,alphabet2);createHuffmanTree(HT,num,alphabet);HuffmanCode HC;CreatHuffmanCode(HT,HC,num);encode(S,HC,num,HT,sum);decode(sum,num,HT);printf("\n"); }while(S.String!="00");}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
关于n个字符的哈弗曼编码的计算时间复杂度为(nlogn)
因为最小堆的插入和删除都需要(logn)的时间,而n-1次的合并就需要n
(logn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306778.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

relation does not exist报错是什么意思_为什么Zookeeper天生就是一副分布式锁的胚子?...

“ 什么是分布式锁&#xff1f;分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中&#xff0c;常常需要协调他们的动作。图片来自 Pexels如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源&#xff0c;那么访问这些资源的时候&#xff0…

netcore一键部署到linux服务器以服务方式后台运行

AntDeploy 是我开发一款开源一键发布插件将本地vs中的代码&#xff0c;一键打包&#xff0c;部署到任意的远程服务器部署方式支持 windows服务&#xff0c;linux服务&#xff0c;docker容器&#xff0c;iis支持增量发布(只更新有修改的)支持一键回滚(出了问题快速恢复)支持查看…

数据结构——基于 Dijsktra 算法的最短路径求解

实验七 基于 Dijsktra 算法的最短路径求解 【实验目的】 掌握图的邻接矩阵表示法&#xff0c;掌握采用邻接矩阵表示法创建图的算法。掌握求解最短路径的 Dijsktra 算法。 【实验内容】 问题描述 一张地图包括 n 个城市,假设城市间有 m 条路径(有向图),每条路径的长度 已知。给…

loadrunner录制事件为0_测试工具LoadRunner常见问题汇总,解决方案整理

LoadRunner是一种预测系统行为和性能的负载测试工具。通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题&#xff0c;可适用于各种体系架构的自动负载测试&#xff0c;能预测系统行为并评估系统性能。我们在使用它进行测试的过程中经常会遇到一些错误&…

.NET应用如何优雅的实现功能定时开关

点击上方蓝字关注“汪宇杰博客”导语我们在打工的时候&#xff0c;总能遇到一种类型的需求&#xff1a;“我想要这个活动广告在双11期间才显示”&#xff0c;“我想要这个API在20号以后才开放”&#xff0c;可能你觉得这个需求没什么难的&#xff0c;写个时间判断不就行了&…

数据结构——图-迪杰斯特拉算法

问题描述 将图以邻接矩阵或邻接表存储&#xff0c;实现Dijkstra算法。 算法设计 迪杰斯特拉算法&#xff1a; 1.假设用带权的邻接矩阵arc&#xff0c;来表示带权有向图&#xff0c;arc[i][j]&#xff0c;表示弧<vi,vj>上的权值。若<vi,vj>不存在&#xff0c;则置…

单体 soa 微服务 区别_漫谈何时从单体架构迁移到微服务?

面对微服务如火如荼的发展&#xff0c;很多人都在了解&#xff0c;学习希望能在自己的项目中帮得上忙&#xff0c;当你对微服务的庐山真面目有所了解后&#xff0c;接下来就是说服自己了&#xff0c;到底如何评估微服务&#xff0c;什么时候使用微服务&#xff0c;什么时间点最…

2020了,最流行的密码依旧是123456

喜欢就关注我们吧&#xff01;密码管理器 NordPass 于日前发布的一份报告中揭示了 2020 年最常见的密码&#xff0c;并提供了有关如何使密码更安全的建议。根据 NordPass 的研究&#xff0c;在今年 200 种最常用的密码中&#xff0c;“123456”位居第一&#xff0c;有 250 万人…

计算机二级和英语四六级是同一个账号吗,英语四六级考试和计算机考试的登录账号和密码一样吗?我好像混了,但是密码一直输不对,...

两个密码都记得直接试就出来了非常的简单&#xff0c;如果实在不行的话重置一下大学英语六级考试(又称CET-6&#xff0c;全称为“College English Test-6”)是由国家统一出题的&#xff0c;统一收费&#xff0c;统一组织考试&#xff0c;用来评定应试人英语能力的全国性的考试&…

C# 中的本地函数

今天我们来聊一聊 C# 中的本地函数。本地函数是从 C# 7.0 开始引入&#xff0c;并在 C# 8.0 和 C# 9.0 中加以完善的。引入本地函数的原因我们来看一下微软 C# 语言首席设计师 Mads Torgersen 的一段话&#xff1a;Mads Torgersen&#xff1a;我们认为这个场景是有用的 —— 您…

数据结构——图-有向图和无向图的邻接表基础

#include <stdio.h> #include <stdlib.h> #define VertexType char //顶点的数据类型&#xff08;char&#xff09; #define VertexMax 20 //最大顶点个数 typedef struct ArcNode//边表 {int adjvex;//存储的是该顶点在顶点数组即AdjList[]中的位置 struct ArcN…

2019山科计算机专业分数线,2019山东科技大学研究生分数线汇总(含2016-2019历年复试)...

2019山东科技大学研究生分数线(含2016-2019历年复试)考研就是人生的第二次高考&#xff0c;是再一次改变自己命运的机会&#xff0c;所谓7分靠努力&#xff0c;3分靠填报&#xff0c;山东科技大学历年研究生复试分数线是2019-2020届考研学子十分关心的问题&#xff0c;以下是如…

b+树时间复杂度_第15期:索引设计(索引组织方式 B+ 树)

谈到索引&#xff0c;大家并不陌生。索引本身是一种数据结构&#xff0c;存在的目的主要是为了缩短数据检索的时间&#xff0c;最大程度减少磁盘 IO。任何有数据的场景几乎都有索引&#xff0c;比如手机通讯录、文件系统(ext4xfsfs)、数据库系统(MySQLOracle)。数据库系统和文件…

结合控制台程序和K8S的CronJob完成定时任务

前言 老黄前段时间遇到了一个数据清洗的需求&#xff0c;其实就是每天凌晨把昨天的数据清洗一遍&#xff0c;归归类。这是一个比较典型的定时任务的处理场景。定时任务可以说就一把利器&#xff0c;几乎每个公司都离不开&#xff0c;它的应用场景也不在少数&#xff0c;比如&am…

数据结构——图-有向带权图的邻接表基础

#include <stdio.h> #include <stdlib.h> #define VertexType char //顶点的数据类型&#xff08;char&#xff09; #define VertexMax 20 //最大顶点个数 typedef struct ArcNode//边表 {int adjvex;//存储的是该顶点在顶点数组即AdjList[]中的位置int weight; …

vs里面mfc是什么_最近!一大批人正在前往文安,究竟发生了什么?

阅读本文前&#xff0c;请您先点击上面蓝色字体“文安家乡群”再点击“关注”&#xff0c;这样您就可以加入文安家乡群了。最近&#xff0c;文安的火车站汽车站&#xff0c;来了一大批外地人&#xff0c;挤爆了文安车站…究竟发生了什么事儿&#xff1f;让这么多人蜂拥而至&…

html 去除max-height,HTML Style maxHeight用法及代码示例

maxHeight属性设置/返回元素的最大高度。 maxHeight属性仅影响block-level元素&#xff0c;绝对或固定位置元素。用法:它用于设置maxHeight属性&#xff1a;object.style.maxHeight "none|length|%|initial|inherit"它用于返回maxHeight属性&#xff1a;object.styl…

数据结构——图-有向带权图的邻接表

#include <stdio.h> #include <stdlib.h> #define VertexType char //顶点的数据类型&#xff08;char&#xff09; #define VertexMax 20 //最大顶点个数 typedef struct ArcNode//边表 {int adjvex;//存储的是该顶点在顶点数组即AdjList[]中的位置int weight; …

ASP.NET Core使用HostingStartup增强启动操作

概念在ASP.NET Core中我们可以使用一种机制来增强启动时的操作&#xff0c;它就是HostingStartup。如何叫"增强"操作&#xff0c;相信了解过AOP概念的同学应该都非常的熟悉。我们常说AOP使用了关注点分离的方式&#xff0c;增强了对现有逻辑的操作。而我们今天要说的…

计算机网络实验arp协议分析,计算机网络ARP地址协议解析实验报告

计算机网络ARP地址协议解析实验报告 (5页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;9.9 积分计算机网络实验报告、实验目的:1. 掌握ARP协议的报文格式2. 掌握ARP协议的工作原理3. 理解ARP高速缓存…