全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

C++数据结构之文件压缩(哈夫曼树)实例详解

C++数据结构之文件压缩(哈夫曼树)实例详解

概要:

项目简介:利用哈夫曼编码的方式对文件进行压缩,并且对压缩文件可以解压

开发环境:windows vs2013

项目概述:

        1.压缩

            a.读取文件,将每个字符,该字符出现的次数和权值构成哈夫曼树

            b.哈夫曼树是利用小堆构成,字符出现次数少的节点指针存在堆顶,出现次数多的在堆底

            c.每次取堆顶的两个数,再将两个数相加进堆,直到堆被取完,这时哈夫曼树也建成

            d.从哈夫曼树中获取哈夫曼编码,然后再根据整个字符数组来获取出现了得字符的编码

            e.获取编码后每次凑满8位就将编码串写入到压缩文件(value处理编码1与它即可,0只移动位)

             f.写好配置文件,统计每个字符及其出现次数,并以“字符+','+次数”的形式保存到配置文件中

         2.解压

             a.读取配置文件,统计所有字符的个数

             b.构建哈夫曼树,读解压缩文件,将所读到的编码字符的这个节点所所含的字符写入到解压缩文件中,知道将压缩文件读完

             c.压缩解压缩完全完成,进行小文件大文件的测试

实例代码:

#pragma once 
#include<vector> 
 
template<class T> 
struct Less 
{ 
  bool operator()(const T& l, const T& r) const 
  { 
    return l < r; 
  } 
}; 
 
template<class T> 
struct Greater 
{ 
  bool operator()(const T& l, const T& r) const 
  { 
    return l > r; 
  } 
}; 
 
template<class T, class Compare> 
class Heap 
{ 
public: 
  Heap() 
  {} 
 
  Heap(T* array, size_t n)   //建堆 
  { 
    _array.reserve(n); 
 
    for (size_t i = 0; i < n; i++) 
    { 
      _array.push_back(array[i]); 
    } 
 
    for (int i = (_array.size() - 2) >> 1; i >= 0; --i) 
    { 
      _AdjustDown(i); 
    } 
  } 
 
  const T& Top()const 
  { 
    return _array[0]; 
  } 
 
  void Push(const T& x) 
  { 
    _array.push_back(x); 
    _AdjustUp(_array.size() - 1); 
  } 
 
  size_t Size() 
  { 
    return _array.size(); 
  } 
 
  void Pop() 
  { 
    assert(_array.size() > 0); 
    swap(_array[0], _array[_array.size() - 1]); 
    _array.pop_back(); 
    _AdjustDown(0); 
  } 
 
  bool Empty() 
  { 
    return _array.size() == 0; 
  } 
 
  void Print() 
  { 
    for (size_t i = 0; i < _array.size(); ++i) 
    { 
      cout << _array[i] << " "; 
    } 
    cout << endl; 
  } 
 
protected: 
  void _AdjustUp(int child)  //上调 
  { 
    Compare ComFunc; 
    int parent = (child - 1) >> 1; 
    while (child) 
    { 
      if (ComFunc(_array[child], _array[parent])) 
      { 
        swap(_array[child], _array[parent]); 
        child = parent; 
        parent = (child - 1) >> 1; 
      } 
      else 
      { 
        break; 
      } 
    } 
  } 
 
 
 
 
  void _AdjustDown(int root)   //下调 
  { 
    Compare ComFunc; 
    int parent = root; 
    int child = root * 2 + 1; 
    while (child < _array.size()) 
    { 
      if (child + 1 < _array.size() && ComFunc(_array[child + 1], _array[child])) 
      { 
        ++child; 
      } 
 
      if (ComFunc(_array[child], _array[parent])) 
      { 
        swap(_array[child], _array[parent]); 
        parent = child; 
        child = parent * 2 + 1; 
      } 
      else 
      { 
        break; 
      } 
    } 
  } 
 
 
 
protected: 
  vector<T> _array; 
 
 
}; 
 
 
 
 
void TestHeap() 
{ 
  int a[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 }; 
  //Heap<int> heap(a, sizeof(a) / sizeof(a[0])); 
  //Heap<int, Less<int>> heap(a, sizeof(a) / sizeof(a[0])); 
  Heap<int, Greater<int>> heap(a, sizeof(a) / sizeof(a[0])); 
  heap.Print(); 
  heap.Push(25); 
  heap.Print(); 
  heap.Pop(); 
  heap.Print(); 
} 




#pragma once 
#include"Heap.h" 
 
template<class T> 
struct HuffmanTreeNode 
{ 
  HuffmanTreeNode<T>* _left; 
  HuffmanTreeNode<T>* _right; 
  HuffmanTreeNode<T>* _parent; 
  T _w;       //权值 
 
 
  HuffmanTreeNode(const T& x) 
    :_w(x) 
    , _left(NULL) 
    , _right(NULL) 
    , _parent(NULL) 
  {} 
 
}; 
 
template<class T> 
class HuffmanTree 
{ 
  typedef HuffmanTreeNode<T> Node; 
public: 
  HuffmanTree() 
    :_root(NULL) 
  {} 
 
  HuffmanTree(T* a, size_t n, const T& invalid = T())  //构建哈夫曼树 
  { 
    struct Compare 
    { 
      bool operator()(Node* l, Node* r) const 
      { 
        return l->_w < r->_w; 
      } 
    }; 
 
    Heap<Node*, Compare> minHeap; 
    for (size_t i = 0; i < n; ++i) 
    { 
      if (a[i] != invalid) 
      { 
        minHeap.Push(new Node(a[i])); 
      } 
    } 
 
    while (minHeap.Size() > 1) 
    { 
      Node* left = minHeap.Top(); 
      minHeap.Pop(); 
      Node* right = minHeap.Top(); 
      minHeap.Pop(); 
      Node* parent = new Node(left->_w + right->_w); 
      parent->_left = left; 
      parent->_right = right; 
      left->_parent = parent; 
      right->_parent = parent; 
      minHeap.Push(parent); 
    } 
    _root = minHeap.Top(); 
  } 
 
 
  Node* GetRoot() 
  { 
    return _root; 
  } 
 
  ~HuffmanTree() 
  { 
    _Destory(_root); 
  } 
 
 
 
 
 
protected: 
  void _Destory(Node* root) 
  { 
    if (root == NULL) 
    { 
      return; 
    } 
 
    _Destory(root->_left); 
    _Destory(root->_right); 
    delete root; 
  } 
 
  HuffmanTree(const HuffmanTree<T>& tree); 
  HuffmanTree& operator=(const HuffmanTree<T>& tree); 
 
protected: 
  Node* _root; 
 
}; 
 
 
void TestHuffmanTree() 
{<pre code_snippet_id="2340790" snippet_file_name="blog_20170418_2_3778260" name="code" class="cpp">#pragma once 
 
#include<iostream> 
using namespace std; 
#include<assert.h> 
#include"HuffmanTree.h" 
 
 
typedef long long LongType; 
struct CharInfo    
{ 
  unsigned char _ch;     //字符 
  LongType _count;     //字符出现的次数 
  string _code;      //huffman编码 
 
  CharInfo(LongType count = 0) 
    :_count(count) 
    , _ch(0) 
    , _code("") 
  {} 
 
 
  bool operator<(const CharInfo& info) const 
  { 
    return _count < info._count; 
  } 
 
  CharInfo operator+(const CharInfo& info) 
  { 
    return CharInfo(_count + info._count); 
  } 
 
  bool operator!=(const CharInfo& info)const 
  { 
    return _count != info._count; 
  } 
}; 
 
 
struct CountInfo 
{ 
  unsigned char _ch;    //字符 
  LongType _count;     //字符出现的次数 
}; 
 
 
 
 
class FileCompress 
{ 
public: 
  FileCompress() 
  { 
    for (size_t i = 0; i < 256; ++i) 
    { 
      _info[i]._ch = i; 
    } 
  } 
 
  void Compress(const char* filename) 
  { 
    assert(filename); 
     
    //统计字符出现的次数,均已二进制方式读写 
    FILE* fout = fopen(filename, "rb"); 
    assert(fout); 
    int ch = fgetc(fout); 
 
    string CompressFile = filename; 
    CompressFile += ".huffman"; 
    FILE* fin = fopen(CompressFile.c_str(), "wb"); 
    assert(fin); 
    CountInfo info; 
 
 
    while (ch != EOF) 
    { 
      _info[(unsigned char)ch]._count++; 
      ch = fgetc(fout); 
    } 
 
    //构建huffman tree 
    CharInfo invalid; 
    invalid._count = 0; 
    HuffmanTree<CharInfo> tree(_info, 256, invalid); 
 
    //生成huffman code 
    GetHuffmanCode(tree.GetRoot()); 
 
    //压缩 
    //写配置文件 
    for (size_t i = 0; i < 256; ++i) 
    { 
      if (_info[i]._count) 
      { 
        info._ch = _info[i]._ch; 
        info._count = _info[i]._count; 
        fwrite(&info, sizeof(info), 1, fin); 
      } 
    } 
 
    info._count = -1; 
    fwrite(&info, sizeof(info), 1, fin); 
 
    fseek(fout, 0, SEEK_SET);   //返回到文件开始 
    ch = fgetc(fout); 
    char value = 0;     //二进制 
    int pos = 0;    //左移位数 
    while (ch != EOF) 
    { 
      string& code = _info[(unsigned char)ch]._code; 
      size_t i = 0; 
      for (i = 0; i < code.size(); ++i) 
      { 
        value <<= 1; 
        ++pos; 
        if (code[i] == '1') 
        { 
          value |= 1; 
        } 
        if (pos == 8)       //满8位写进文件中 
        { 
          fputc(value, fin); 
          value = 0; 
          pos = 0; 
        } 
      } 
      ch = fgetc(fout); 
    } 
    if (pos) 
    { 
      value <<= (8 - pos); 
      fputc(value, fin); 
    } 
    fclose(fin); 
    fclose(fout); 
  } 
 
  void GetHuffmanCode(HuffmanTreeNode<CharInfo>* root)    //huffman编码 
  { 
    if (root == NULL) 
    { 
      return; 
    } 
 
    if (root->_left == NULL && root->_right == NULL) 
    { 
      HuffmanTreeNode<CharInfo> *parent, *cur; 
      cur = root; 
      parent = cur->_parent; 
      string& code = _info[(unsigned char)root->_w._ch]._code; 
      while (parent) 
      { 
        if (cur == parent->_left) 
        { 
          code += '0'; 
        } 
        else 
        { 
          code += '1'; 
        } 
        cur = parent; 
        parent = cur->_parent; 
      } 
      reverse(code.begin(), code.end()); 
    } 
    GetHuffmanCode(root->_left); 
    GetHuffmanCode(root->_right); 
  } 
 
  //解压 
  void UnCompress(const char* filename) 
  { 
    assert(filename); 
    string UnCompressFile = filename; 
    size_t index = UnCompressFile.rfind('.'); 
    assert(index != string::npos); 
    UnCompressFile = UnCompressFile.substr(0, index); 
    UnCompressFile += ".unhuffman"; 
    FILE* fout = fopen(filename, "rb"); 
    assert(fout); 
    FILE* fin = fopen(UnCompressFile.c_str(), "wb"); 
    assert(fin); 
    CountInfo info; 
    fread(&info, sizeof(CountInfo), 1, fout); 
 
    //读配置信息 
    while (1) 
    { 
      fread(&info, sizeof(CountInfo), 1, fout); 
      if (info._count == -1) 
      { 
        break; 
      } 
      _info[(unsigned char)info._ch]._ch = info._ch; 
      _info[(unsigned char)info._ch]._count = info._count; 
    } 
 
    //重建huffman树 
    CharInfo invalid; 
    invalid._count = 0; 
    HuffmanTree<CharInfo> tree(_info, 256, invalid); 
    HuffmanTreeNode<CharInfo>* root = tree.GetRoot(); 
    HuffmanTreeNode<CharInfo>* cur = root; 
    LongType count = root->_w._count; 
    int value = fgetc(fout); 
 
    if (value == EOF)       //只有一种字符 
    { 
      if (info._ch != 0) 
      { 
        while (cur->_w._count--) 
        { 
          fputc(cur->_w._ch, fin); 
        } 
      } 
    } 
    else 
    { 
      while (value != EOF) 
      { 
        int pos = 7; 
        char test = 1; 
        while (pos >= 0) 
        { 
          if (value & (test << pos)) 
          { 
            cur = cur->_right; 
          } 
          else 
          { 
            cur = cur->_left; 
          } 
          if (cur->_left == NULL && cur->_right == NULL) 
          { 
            fputc(cur->_w._ch, fin); 
            cur = root; 
            if (--count == 0) 
            { 
              break; 
            } 
          } 
          --pos; 
        } 
        value = fgetc(fout); 
      } 
    } 
 
    fclose(fout); 
    fclose(fin); 
  } 
 
protected: 
  CharInfo _info[256];   //所有字符信息 
}; 
 
void TestFileCompress() 
{ 
  FileCompress fc; 
  //fc.Compress("实验.doc"); 
  //fc.UnCompress("实验.doc.huffman"); 
  //fc.Compress("qq.JPG"); 
  //fc.UnCompress("qq.JPG.huffman"); 
  //fc.Compress("www.MP3"); 
  //fc.UnCompress("www.MP3.huffman"); 
 
  fc.Compress("yppppp.txt"); 
  fc.UnCompress("yppppp.txt.huffman"); 
}</pre><br> 
int array[10] = { 2, 4, 6, 9, 7, 8, 5, 0, 1, 3 };HuffmanTree<int> t(array, 10);} 
<pre></pre> 
<p></p> 
<pre></pre> 
<p></p> 
<p></p> 
<p></p> 
<pre code_snippet_id="2340790" snippet_file_name="blog_20170418_3_1128302" name="code" class="cpp">#include <iostream> 
#include <assert.h> 
#include <windows.h> 
using namespace std; 
 
#include"Heap.h" 
#include"HuffmanTree.h" 
#include"FileCompress.h" 
 
int main() 
{ 
  //TestHeap();   
  TestHuffmanTree(); 
  TestFileCompress(); 
 
 
  system("pause"); 
  return 0; 
}</pre><br> 
<br> 
<p></p> 
<p><br> 
</p> 
<p><br> 
</p> 
<link rel="stylesheet" href="http://static.blog.csdn.net/public/res-min/markdown_views.css?v=1.0" rel="external nofollow" > 

 以上就是哈夫曼树的实例详解,如有疑问请留言或者到本站社区交流,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


# C++数据结构之文件压缩(哈夫曼树)  # C++数据结构之文件压缩  # 数据结构哈夫曼树  # C++深入讲解哈夫曼树  # C++详解哈夫曼树的概念与实现步骤  # C++实现哈夫曼树的方法  # C++实现哈夫曼树编码解码  # C++实现哈夫曼树算法  # C++数据结构与算法之哈夫曼树的实现方法  # C++ 哈夫曼树对文件压缩、加密实现代码  # 解析C++哈夫曼树编码和译码的实现  # C++实现哈夫曼树简单创建与遍历的方法  # C++使用数组来实现哈夫曼树  # 配置文件  # 解压缩  # 压缩文件  # 如有  # 数据结构  # 希望能  # 然后再  # 并以  # 就将  # 谢谢大家  # 再将  # 读到  # 写好  # 均已  # 所含  # 与它  # 写进  # 疑问请  # 大文件  # 文件压缩 


相关文章: 常州企业网站制作公司,全国继续教育网怎么登录?  如何正确下载安装西数主机建站助手?  香港服务器建站指南:外贸独立站搭建与跨境电商配置流程  C++如何将C风格字符串(char*)转换为std::string?(代码示例)  建站之星安装后如何自定义网站颜色与字体?  如何通过老薛主机一键快速建站?  建站主机无法访问?如何排查域名与服务器问题  ppt在线制作免费网站推荐,有什么下载免费的ppt模板网站?  移民网站制作流程,怎么看加拿大移民官网?  ,网页ppt怎么弄成自己的ppt?  建站之星后台管理:高效配置与模板优化提升用户体验  C++用Dijkstra(迪杰斯特拉)算法求最短路径  怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?  如何通过商城自助建站源码实现零基础高效建站?  宝塔Windows建站如何避免显示默认IIS页面?  如何在云虚拟主机上快速搭建个人网站?  购物网站制作公司有哪些,哪个购物网站比较好?  建站之星如何快速生成多端适配网站?  广州网站建站公司选择指南:建站流程与SEO优化关键词解析  武清网站制作公司,天津武清个人营业执照注销查询系统网站?  佛山企业网站制作公司有哪些,沟通100网上服务官网?  c# 在高并发场景下,委托和接口调用的性能对比  如何在宝塔面板中创建新站点?  枣阳网站制作,阳新火车站打的到仙岛湖多少钱?  ,交易猫的商品怎么发布到网站上去?  如何用美橙互联一键搭建多站合一网站?  制作网站公司那家好,网络公司是做什么的?  建站之星价格显示格式升级,你的预算足够吗?  宝塔建站无法访问?如何排查配置与端口问题?  网站制作的步骤包括,正确网址格式怎么写?  建站主机CVM配置优化、SEO策略与性能提升指南  如何在万网ECS上快速搭建专属网站?  建站之星安装失败:服务器环境不兼容?  如何零成本快速生成个人自助网站?  代购小票制作网站有哪些,购物小票的简要说明?  网站制作企业,网站的banner和导航栏是指什么?  动图在线制作网站有哪些,滑动动图图集怎么做?  网站制作模板下载什么软件,ppt模板免费下载网站?  香港服务器WordPress建站指南:SEO优化与高效部署策略  网站专业制作公司有哪些,做一个公司网站要多少钱?  微信网站制作公司有哪些,民生银行办理公司开户怎么在微信网页上查询进度?  建站上市公司网站建设方案与SEO优化服务定制指南  建站主机数据库如何配置才能提升网站性能?  如何在IIS7上新建站点并设置安全权限?  关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)  阿里云高弹*务器配置方案|支持分布式架构与多节点部署  黑客如何利用漏洞与弱口令入侵网站服务器?  php条件判断怎么写_ifelse和switchcase的使用区别【对比】  黑客入侵网站服务器的常见手法有哪些?  百度网页制作网站有哪些,谁能告诉我百度网站是怎么联系? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。