基于哈夫曼树的英文文本数据压缩算法

(1)问题描述

   输入一串字符串,根据给定的字符串中字符出现的频率建立相应的哈夫曼树,构造哈夫曼编码表,在此基础上可以对压缩文件进行压缩(即编码),同时可以对压缩后的二进制编码文件进行解压(即译码)。

(2)输入要求

多组数据,每组数据1行,为一个字符串(只考虑26个小写字母即可)。当输入字符串为“0”时,输入结束。

(3)输出要求

每组数据输出2n+3行(n为输入串中字符类别的个数。第1行为统计出来的字符出现频率(只输出存在的字符,格式为:字符:频度),每两组字符之间用一个空格分隔,字符按照 ASCII 码从小到大的顺序排列。第2行至第2n行为哈夫曼树的存储结构的终态,如主教材139页表5.2(b),一行当中的数据用空格分隔。第2n+1行为每个字符的哈夫曼编码(只输出存在的字符,格式为:

字符:编码),每两组字符之间用一个空格分隔,字符按照ASCII码从小到大的顺序排列。第2n+2行为编码后的字符串,第2n+3行为解码后的字符串(与输入的字符串相同)。

(4)输入样式

aaaaaaabbbbbccdddd (案例1)

aabccc            (案例2)

0

(5)输出样例

a:7  b:5  c:2  d:4   (案例1)

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  11  7  2  5

7  18  0  1  6
 a:0   b:10   c:110   d:111 
00000001010101010110110111111111111

aaaaaaabbbbbccdddd 
a:2   b:l   c:3      (案例2)
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

代码如下(包含注释解释部分代码):

#include<iostream>
#include<cstring>
#include<string>using namespace std;struct Num
{char ch; //字符int num; //字符对应个数
}an[7000], temp;//sort1根据字符个数从大到小进行排序
void sort1(Num* bn)
{Num te; //相当于一个临时变量,用作保存数据来完成数据的交换int i, j;//冒泡排序:for (j = 0; j < 26; j++)  //总共二十六个字母,则大循环进行二十六次(0-25共二十六次)for (i = 0; i < 26-j-1; i++) {if (bn[i].num < bn[i + 1].num){te = bn[i];bn[i] = bn[i + 1];bn[i + 1] = te;}}
}//sort2根据字符的ASCII码值从小到大进行排序
void sort2(Num* bn, int n) //n为统计的所输入数据中的字符种类数
{Num te;int i, j;//冒泡排序:for (j = 0; j < n; j++)for (i = 0; i < n-j-1; i++){if (bn[i].ch > bn[i + 1].ch && bn[i + 1].num > 0) //交换条件为当前字符的权重大于下一个字符的权重,且下一个字符的数量大于0,即下一个字符存在{te = bn[i];bn[i] = bn[i + 1];bn[i + 1] = te;}}
}//哈夫曼数的结构体
typedef struct
{int weight; //权重int parent, lchild, rchild; //父节点,左右孩子节点int vis; //作为一个标识符使用(防止重复进行select过程)char ch; //节点对应的字符char strc[60]; //哈夫曼编码int len;int num; //某个字符在哈夫曼树中的个数
}HTNode, * HuffmanTree; //HTNode == * HuffmanTree(解引用)//Select根据权重来安排哈夫曼树中节点的位置
//第一个参数为指向哈夫曼树的指针的引用,第二个参数为所处哈夫曼树中节点的个数,第三第四个参数为两个标识符,且参数为引用传递,可以通过函数改变该标识符的值
void Select(HuffmanTree& HT, int k, int& s1, int& s2)
{int i;HTNode h1, h2; //HTNode对应的应该是指向哈夫曼树的指针int t1, t2; //作为标记,分别标记h1,h2对应节点所处的位置t1 = t2 = 0; h1 = HT[1];h1.weight = 999999;for (i = 1; i <= k; i++) //循环共k个节点,分别与现有的h1.weight比较权重,从而选出所含权重最小的节点值并将该值赋值给h1.weight{if (HT[i].weight <= h1.weight && HT[i].vis == 0){h1 = HT[i];t1 = i;}}h2 = HT[2];h2.weight = 999999;for (i = 1; i <= k; i++) //再对h2进行和h1相同的选择赋值过程{if (HT[i].weight <= h2.weight && t1 != i && HT[i].vis == 0){h2 = HT[i];t2 = i;}}//在h1和h2权重相同的情况下,将所含字符数更少的字符放在前面if (h1.weight == h2.weight && HT[t1].num > HT[t2].num){int temp;temp = t1;t1 = t2;t2 = temp;}//将更新后的t1,t2分别赋值给s1,s2s1 = t1;s2 = t2;//令vis=1,标识HT[s1]和HT[s2]这两个节点以及经过了Select作用,防止重复进行该过程HT[s1].vis = 1;HT[s2].vis = 1;return;
}//哈夫曼树的编码函数
//第一个参数是指向哈夫曼树指针的引用,第二个参数是字符串的长度,第三个参数为字符串,第四个参数是哈夫曼树中的第n个节点,第五个参数为编码(左孩子为'0',右孩子为'1')
void code(HuffmanTree& HT, int len, const char str[], int n, char cc)
{int i;//HT[n].strc的前len-2个字符都设置为str[i],第len-1个字符设置为编码值cc,第len个字符设置为空'\0'for (i = 0; i < len - 1; i++)HT[n].strc[i] = str[i];HT[n].strc[i] = cc;HT[n].strc[i + 1] = '\0';//利用递归完成整棵树的编码//如果左子树不为空,则一直编码直到左子树为空if (HT[n].lchild != 0)code(HT, len + 1, HT[n].strc, HT[n].lchild, '0');//如果右子树不为空,则一直编码直到右子树为空if (HT[n].rchild != 0)code(HT, len + 1, HT[n].strc, HT[n].rchild, '1');
}//哈夫曼树的构造(利用了Select函数进行选择排序以及Code函数进行编码)
//第一个参数是一个指向哈夫曼树的指针的引用,第二个参数为n个子叶节点(即没有左右孩子的节点),第三个参数为
void CreateHuffmanTree(HuffmanTree& HT, int n, char* str, int n1)
{int s1, s2;s1 = s2 = 0;if (n <= 1) //如果子叶节点小于一,则直接返回,完成哈夫曼树的构造return;int m = 2 * n - 1; //n个叶子节点的哈夫曼树有2n-1个节点//通过new语法创建哈夫曼树节点HT = new HTNode[m + 1];//初始化哈夫曼树中的所有节点for (int i = 1; i <= m; i++){HT[i].parent = 0; HT[i].lchild = 0; HT[i].rchild = 0;HT[i].vis = 0; HT[i].len = 0; HT[i].num = i;HT[i].weight = 0;}for (int i = 1; i <= n; i++){//an[]是创建的结构体数组//将结构体数组中的数据依次赋值给哈夫曼树中的节点HT[i].weight = an[i - 1].num;HT[i].ch = an[i - 1].ch;}//总共m个节点,其中有n个叶子节点,则循环从n+1开始,到m截至,对n+1 -- m 中的节点进行排序for (int i = n + 1; i <= m; i++){Select(HT, i - 1, s1, s2);//同一个父节点推出两个左右子节点HT[s1],HT[s2]HT[s1].parent = i;HT[s2].parent = i;//父节点的左孩子为s1HT[i].lchild = s1;//父节点的右孩子为s2HT[i].rchild = s2;//父节点的权重为左孩子的权重加上右孩子的权重HT[i].weight = HT[s1].weight + HT[s2].weight;}int len = HT[m].len;HT[m].strc[len] = '1';//根据 左--0,右--1 来进行哈夫曼树的编码 if (HT[m].lchild)code(HT, 1, "", HT[m].lchild, '0');if (HT[m].rchild)code(HT, 1, "", HT[m].rchild, '1');return;
}int main()
{HuffmanTree h;int n, n1;char str[700], str2[700];cout << "请输入字符串(输入0时结束算法)" << endl;while (cin >> str) //为字符串str完成输入,当输入'0'时结束while循环{if (str[0] == '0' && str[1] == '\0')break;n1 = 0;for (int i = 0; i < 27; i++){an[i].num = 0; //初始化所有字母的个数为0//将an[0-25]分别填放a~z这二十六个字母an[i].ch = 'a' + i;}n = strlen(str); //n为字符串str的长度for (int i = 0; i < n; i++){//根据输出的字符串str来获取其中每个字母所含的个数 //eg.如果某个str[i] == b ,则str[i]-'a' ==1 -- 根据ASCII码计算,即为an[1].num加一同时an[1]对应的字母字符也是b,相当于记录了str字符串中所含字母b的个数加一an[str[i] - 'a'].num++; str2[i] = str[i];str2[i + 1] = '\0';}//根据字符个数从大到小进行排序sort1(an);for (int i = 0; i < 26; i++){if (an[i].num != 0)n1++;//n1统计an中所含的字符数(如果an[i].num == 0 则说明an[i]对应的字符字母不存在)}//根据字符的ASCII码值从小到大进行排序sort2(an, n1);//创建哈夫曼数(CreateHuffmanTree中包含Select和Code函数)CreateHuffmanTree(h, n1, str, n1);//如果字符串str中只有一个字符if (n1 == 1){h = new HTNode[3];h[1].weight = n;h[1].parent = h[1].lchild = h[1].rchild = 0;h[1].ch = str[0];h[1].strc[0] = '0';h[1].strc[1] = '\0';}//输出:cout << "输出为: " << endl;//输出每个字符在字符串中出现了几次int f = 0;for (int i = 0; i < 26; i++)if (an[i].num > 0){f++;cout << an[i].ch << ":" << an[i].num;if (f == n1)cout << endl;elsecout << " ";}//输出哈夫曼数的储存结构的终态for (int i = 1; i <= 2 * n1 - 1; i++){cout << i << " " << h[i].weight << " " << h[i].parent << " " << h[i].lchild << " " << h[i].rchild << endl;}//输出每个字符的哈夫曼编码for (int i = 1; i < n1; i++)cout << h[i].ch << ":" << h[i].strc << " ";cout << h[n1].ch << ":" << h[n1].strc;cout << endl;//输出解码后的字符串for (int i = 0; i < n; i++){for (int j = 1; j <= n1; j++)if (h[j].ch == str[i])cout << h[j].strc;}cout << endl;cout << str << endl;//重置哈夫曼数中的数据for (int i = 1; i <= 2 * n1 - 1; i++){h[i].parent = 0;h[i].lchild = 0; h[i].rchild = 0;h[i].vis = 0;h[i].len = 0;h[i].num = i;}cout << "请继续输入字符串(输入0结束算法)" << endl;}return 0;
}

程序运行结果:

基于哈夫曼树的英文文本数据压缩算法相关推荐

  1. 基于哈夫曼树的数据压缩算法

    计算机科学与技术系 实 验 报 告 专业名称 计算机科学与技术 课程名称 数据结构与算法 班 级 17计科2班 综合实验2 基于哈夫曼树的数据压缩算法 实验日期 2019.04.29 综合实验二 基于 ...

  2. 数据结构“基于哈夫曼树的数据压缩算法”的实验报告

    一个不知名大学生,江湖人称菜狗 original author: jacky Li Email : 3435673055@qq.com Last edited: 2022.11.20 目录 数据结构& ...

  3. BJFU_数据结构习题_262基于哈夫曼树的数据压缩算法

    欢迎登录北京林业大学OJ系统 http://www.bjfuacm.com 262基于哈夫曼树的数据压缩算法 描述 输入一串字符串,根据给定的字符串中字符出现的频率建立相应哈夫曼树,构造哈夫曼编码表, ...

  4. 数据结构 基于哈夫曼树的数据压缩算法

    数据结构 基于哈夫曼树的数据压缩算法 实验目的 实验内容 实验提示 实验代码 实验小结 实验目的 1.掌握哈夫曼树的构造算法. 2.掌握哈夫曼编码的构造算法. 实验内容 问题描述 输入一串字符串,根据 ...

  5. 赫夫曼编码(基于赫夫曼树的实现)

    上一篇文章中我们探讨了赫夫曼树的基本原理和构造方式,而赫夫曼编码可以很有效地压缩数据(通常可以节约20%-90%的空间,具体压缩率依赖于数据的特性). 名词:定长编码,边长编码,前缀码(装B用的) 定 ...

  6. 哈夫曼编码(基于哈夫曼树-最优二叉树,不唯一)、B树(b-树)、B+树

    整合自: http://blog.csdn.net/shuangde800/article/details/7341289 http://www.cnblogs.com/Jezze/archive/2 ...

  7. 3001基于哈夫曼树的数据压缩算法(附思路及注释)

    写在最前:我的思路用到了stl的map,对组pair相关知识. 描述 输入一串字符串,根据给定的字符串中字符出现的频率建立相应哈夫曼树,构造哈夫曼编码表,在此基础上可以对待压缩文件进行压缩(即编码), ...

  8. 数据结构实验——基于哈夫曼树的数据压缩算法

    /* 注:输入为多行字符串,以"0"结尾:例:abc def 0 此程序无法执行由单个字符组成的字符串. */ #include<iostream> #include& ...

  9. 利用哈夫曼树实现英文短文的压缩与解压

    #include <stdio.h> //主要包括常用的输入/输出函数 #include <string.h> //主要包括常用的字符串操作函数 #include <st ...

最新文章

  1. 机翻降重?掩饰抄袭?SCI期刊上的这些「奇言怪语」,不少来自中国作者
  2. Node.jsNPM的安装与配置(转)
  3. 吉林考生多少分能考上哈工大计算机专业,福建考生多少分能上哈工大?
  4. 第八届蓝桥杯第七题日期问题
  5. 图卷积网络GCN理解
  6. C++实现RTMP协议发送H.264编码及AAC编码的音视频,摄像头直播
  7. 【P20】PCM1794全平衡解码模块电路
  8. GBASE监控工具简介
  9. msfconsole的简单使用
  10. win10添加惠普hp laserjet 1010HB打印机
  11. Linux 下固态硬盘恢复误删除文件
  12. 东北大学秦皇岛分校计算机类排名,东北大学秦皇岛分校全国排名,2021东北大学秦皇岛分校排名榜...
  13. php在html中无法解析json数据,json字符串无法解析的问题
  14. C语言:链表实现二进制数加1运算
  15. DS18B20数字温度传感器及单总线协议规定
  16. instance在oracle意思,INSTANCE_NAME的含义及作用
  17. 2020年7月5日第十一届蓝桥杯第一场省赛试题及详解(Java本科B组)
  18. 基于proe的阀体零件的机械加工工艺及夹具设计
  19. CF597 (Div. 2)题解
  20. 【视频处理】模拟视频与数字视频的区别

热门文章

  1. Linux局域网传文件到iPad上
  2. 【转载】人的一生最后悔什么
  3. Vue项目保存代码之后页面自动更新
  4. 日常使用中的台式电脑应该如何配置
  5. Python入门介绍
  6. 【电气专业知识问答】问:塑料外壳式断路器的结构、运行特点和保护功能是什么?
  7. Competing Risks (竞争风险)
  8. Android的,iOS的,PHP的,大数据的,Java的,web前端的,C++,Python等干货分享
  9. 解决firefox疯狂读硬盘的问题
  10. 安装HElib并运行示例程序