diff options
author | Maxim Pimenov <m@maps.me> | 2015-07-03 20:25:19 +0300 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 02:56:57 +0300 |
commit | 097618caddc3734e141ef18275f2ab3672f1f8f4 (patch) | |
tree | 1c2f8cce36745a1913c92a315156fa83555dcca8 /coding/huffman.cpp | |
parent | 84d1eb88a17e628bedbbbb98f0d275a1eb165605 (diff) |
[omim] [coding] A Huffman coding implementation.
Diffstat (limited to 'coding/huffman.cpp')
-rw-r--r-- | coding/huffman.cpp | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/coding/huffman.cpp b/coding/huffman.cpp new file mode 100644 index 0000000000..acdd945303 --- /dev/null +++ b/coding/huffman.cpp @@ -0,0 +1,78 @@ +#include "coding/huffman.hpp" + +#include "base/logging.hpp" + +namespace coding +{ +HuffmanCoder::~HuffmanCoder() +{ + try + { + DeleteHuffmanTree(m_root); + } + catch (...) + { + LOG(LWARNING, ("Caught an exception when deleting a Huffman tree.")); + } +} + +void HuffmanCoder::Init(vector<strings::UniString> const & data) +{ + BuildHuffmanTree(data.begin(), data.end()); + BuildTables(m_root, 0); + DeleteHuffmanTree(m_root); + m_root = nullptr; +} + +bool HuffmanCoder::Encode(uint32_t symbol, Code & code) const +{ + auto it = m_encoderTable.find(symbol); + if (it == m_encoderTable.end()) + return false; + code = it->second; + return true; +} + +bool HuffmanCoder::Decode(Code const & code, uint32_t & symbol) const +{ + auto it = m_decoderTable.find(code); + if (it == m_decoderTable.end()) + return false; + symbol = it->second; + return true; +} + +void HuffmanCoder::BuildTables(Node * root, uint32_t path) +{ + if (!root) + return; + if (root->isLeaf) + { + Code code(path, root->depth); + m_encoderTable[root->symbol] = code; + m_decoderTable[code] = root->symbol; + return; + } + BuildTables(root->l, path); + BuildTables(root->r, path + (static_cast<uint32_t>(1) << root->depth)); +} + +void HuffmanCoder::DeleteHuffmanTree(Node * root) +{ + if (!root) + return; + DeleteHuffmanTree(root->l); + DeleteHuffmanTree(root->r); + delete root; +} + +void HuffmanCoder::SetDepths(Node * root, uint32_t depth) +{ + if (!root) + return; + root->depth = depth; + SetDepths(root->l, depth + 1); + SetDepths(root->r, depth + 1); +} + +} // namespace coding |