哈夫曼树、哈弗曼编码:压缩,解压文本文件

哈夫曼树、哈弗曼编码:压缩,解压文本文件

  • 由文本文件生成哈夫曼编码,即:压缩
    *思路、步骤
    • 性能分析
  • 代码
    *需注意的的问题
    *不足与优化
  • 译码,即:解压
    *思路步骤
    *代码
    *需注意的问题

由文本文件生成哈夫曼编码

思路、步骤:

1.读入文本文件的内容,并按照每一个不同字符出现的频率赋予相应的权重。这里因为我需要读入汉字(注意汉字及汉语标点符号在计算机中的存储都是两位字符类型大小),所以这里我统计每个汉字或标点出现的次数的方法是建立一个结构体数组(设不同的汉字由NUM种,宏定义可手动修改,当然也可改为自动添加),每读入一个新的汉字就从结构体数组的开头开始检测是否出现过,出现过则会在检测到结尾之前匹配成功,该汉字数目加一,不成功则在结束检测时把末尾结构体元素设为此汉字,以此类推直到读入到文件末尾。

**一定要注意这里是读取汉字时的情况!!**若读英文字母文本则简单的多,因为英文所有字符的ascii码分布都在0 - 255 之间,所以我们只需要建立一个大小为256的数组即可以英文字符的ascii码做下标存储并记录字符出现次数,这样会大大减小时间复杂度!!

性能分析:
  1. 读汉字时,新读入的一个汉字必须经过和之前已经存在的汉字一个一个的比较才能确定是否出现过。那么在最坏情况下,若文本文件中的n个汉字均各不相同,那么其时间复杂度将会达到O(n^2)的大小,当文件大小过大时这是无法想象的。(如果你有时间、空间复杂度更小的方法欢迎在评论区里提出~
  2. 读英文文本时的情况要好得多,因为字符的ascii码值唯一,所以能以O(1)的时间复杂度确定字母是否出现并累加其出现次数。

代码

下面上代码,**亲自测试无误,源代码无删改,请放心观看使用!!

//----------------------------------------------------------------------
//作者:@你隔壁的小傻子
//更新时间:2019 - 12 - 21
//多有不足,感谢支持
//----------------------------------------------------------------------
/*思路:
赫夫曼树、前缀码
-读入txt文件
--判断有多少个不同字符,按比例赋权值
-构造赫夫曼树
-生成前缀码
-前缀码存储到文件中  //完成第一步
-译码
--存储到文件中
*/
#include<iostream>
#include<stdlib.h>
#include<windows.h>
#include<vector>
#include<conio.h>
#include<string.h>
#include<map>
#include<math.h>
#include<fstream>
using namespace std;

#define out_file "d:huffman_code.txt"//存放二进制数
#define in_file "d:source.txt"    //原文件
#define translate_file "d:translate.txt"       //存放译码后信息,可与原文件比较
#define NUM 101       //假定文件中最多有多少种不同汉字,可改为越界自动添加
//定义每个汉字的属性结构体
typedef struct character
{
   
    char a[3]= {
   0};//保存的汉字
    int num = 0;//该汉字的数目
    float weight;//该汉字权重
} charac;
//节点结构体
typedef struct Huffman_Hashtable
{
   
    double weight;//权
    unsigned int parent;
    unsigned int lchild;
    unsigned int rchild;
    bool flag_ = false; //在选择最小权重节点是作为标记
} Huf_Hashtable, *huftre;

//--------------------------------------------编码并存储-----------------------------------//

//从txt文件中读入数据到data[]中
//这里因为是汉字所以采用了这种做法,
//如果是英文字母可以采用创建一个256
//大小的字符数组并将字符以他们的ascii
//值作为下标存储在数组中,这样在文本
//数据很多时能大大优化时间复杂度
int read_txt(charac *data)
{
   
    int num = 1;//指最远位置上的汉字的下一位
    ifstream in(in_file);
    if(!in.is_open())        //处理异常
    {
   
        cout << "cannot open file";
        system("pause");
    }
    in.seekg(0, ios::beg);
    while(in.peek()!=EOF)//将文件中内容读到结构体数组中
    {
   
        in.read(data[0].a, 2 * sizeof(char));
        for (int z = 1; z <= num; ++z)
        {
   
            if(strcmp(data[0].a,data[z].a) == 0)//已存在相同汉字
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值