21xrx.com
2024-12-27 20:27:50 Friday
登录
文章检索 我的文章 写文章
C++实现文件压缩
2023-06-29 12:26:01 深夜i     --     --
C++编程 文件压缩 压缩算法 数据结构 文件IO

随着计算机技术的不断发展,人们需要处理的数据量越来越大。因此,为了节省存储空间,文件的压缩成为了必要的选择。C++语言作为一门经典的编程语言,在文件压缩方面有着良好的实现能力。

在C++中,文件压缩可以通过STL库中的压缩算法实现。其中,较为常用的算法有哈夫曼编码和LZW编码。哈夫曼编码利用每个字符出现的频率来构建一个二叉树,并将字符转化为对应的编码。此编码方式具有高压缩比和适应各种数据类型的优点。LZW编码则是通过字典的方式实现,将连续出现的字符转化为对应的编码。相比于哈夫曼编码,LZW编码在压缩速度方面更具有优势。不过需要注意的是,压缩的方式不同,解压时需要对应的解压算法。

以下代码展示了通过STL库中的哈夫曼编码算法实现文件压缩:


#include <iostream>

#include <fstream>

#include <string>

#include <queue>

#include <unordered_map>

#include <vector>

#include <algorithm>

using namespace std;

struct Node {

  char ch;

  int freq;

  Node* left;

  Node* right;

  Node(char c, int f, Node* l = nullptr, Node* r = nullptr)

    : ch(c), freq(f), left(l), right(r)

  

  

  ~Node()

  

    delete left;

    delete right;

  

};

struct Comp {

  bool operator()(Node* a, Node* b) const

  

    return a->freq > b->freq;

  

};

void build_freq_table(string& str, unordered_map<char, int>& freq_table)

{

  for (char c : str) {

    if (freq_table.count(c)) {

      freq_table[c]++;

    }

    else {

      freq_table[c] = 1;

    }

  }

}

Node* build_huffman_tree(unordered_map<char, int>& freq_table)

{

  priority_queue<Node*, vector<Node*>, Comp> pq;

  for (auto p : freq_table) {

    pq.push(new Node(p.first, p.second));

  }

  while (pq.size() > 1) {

    Node* a = pq.top();

    pq.pop();

    Node* b = pq.top();

    pq.pop();

    pq.push(new Node('\0', a->freq + b->freq, a, b));

  }

  return pq.top();

}

unordered_map<char, string> build_encoding_table(Node* root)

{

  unordered_map<char, string> encoding_table;

  function<void(Node*, string)> build = [&](Node* node, string code)

  {

    if (!node) {

      return;

    }

    if (!node->left && !node->right) {

      encoding_table[node->ch] = code;

    }

    build(node->left, code + "0");

    build(node->right, code + "1");

  };

  build(root, "");

  return encoding_table;

}

void encode(string& str, unordered_map<char, string>& encoding_table, string& compressed)

{

  for (char c : str) {

    compressed += encoding_table[c];

  }

}

void save_compressed_file(string& compressed, string& filename)

{

  ofstream output(filename, ios::binary);

  int length = compressed.length();

  output.write(reinterpret_cast<const char*>(&length), sizeof(int));

  output.write(compressed.c_str(), (length + 7) / 8);

  output.close();

}

void compress_file(string& filename, string& compressed_filename)

{

  ifstream input(filename, ios::binary);

  string str((istreambuf_iterator<char>(input)), istreambuf_iterator<char>());

  unordered_map<char, int> freq_table;

  build_freq_table(str, freq_table);

  Node* root = build_huffman_tree(freq_table);

  unordered_map<char, string> encoding_table = build_encoding_table(root);

  string compressed;

  encode(str, encoding_table, compressed);

  save_compressed_file(compressed, compressed_filename);

  delete root;

}

int main()

{

  string filename = "sample.txt";

  string compressed_filename = "sample.bin";

  compress_file(filename, compressed_filename);

  return 0;

}

在以上代码中,首先读取输入文件内容,并计算字符频率表;接着使用字符频率数据构建哈夫曼树,并生成每个字符对应的编码表;最后通过编码表将字符串内容进行压缩,并将压缩后的内容保存至二进制文件中。

总的来说,C++通过STL库和自定义数据结构实现文件压缩十分方便。需要注意的是,不同的压缩算法在压缩率和压缩速度方面存在差异,应选择适合自己需要的算法。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复