Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
Huffman.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
43#ifndef HUFFMAN_H
44#define HUFFMAN_H
45
46#include <memory>
47#include <istream>
48#include <tpl_binNodeUtils.H>
49#include <tpl_treap.H>
50#include <tpl_binHeap.H>
51#include <tpl_dynMapTree.H>
52#include <bitArray.H>
53#include <ah-errors.H>
54
55namespace Aleph {
56
57struct Huffman_Node;
58
60
62
63struct Huffman_Node : public BinHeap<size_t>::Node
64{
66
68
69public:
70 Huffman_Node() : BinHeap<size_t>::Node(0), bin_node(nullptr), freq_node(nullptr)
71 {
72 /* empty */
73 }
74
76 : BinHeap<size_t>::Node(0), bin_node(node), freq_node(nullptr)
77 {
78 /* empty */
79 }
80
82 { /* bin_node memory must not be released here */
83 }
84};
85
87
88static inline const size_t &get_freq(Huffman_Node *huffman_node) noexcept
89{
90 return huffman_node->get_key();
91}
92
93static inline void increase_freq(Huffman_Node *huffman_node) noexcept
94{
95 huffman_node->get_key()++;
96}
97
98static inline void set_freq(Huffman_Node *huffman_node, const size_t &freq) noexcept
99{
100 huffman_node->get_key() = freq;
101}
102
104static inline bool is_leaf(BinNode<std::string> *p) noexcept
105{
106 return LLINK(p) == nullptr and RLINK(p) == nullptr;
107}
108
115{
120
122
123 std::string end_symbol_;
124 size_t text_len_;
125
127 {
128 if (is_leaf(p))
129 {
130 const std::string &str = p->get_key();
131 code_map_.insert(str, BitArray(array));
132 return;
133 }
134 array.push(0);
135 build_prefix_encoding(LLINK(p), array);
136 array.pop();
137 array.push(1);
138 build_prefix_encoding(RLINK(p), array);
139 array.pop();
140 }
141
143 {
144 ah_domain_error_if(root_ == nullptr) << "Huffman encoding tree has not been generated";
145
146 BitArray array(0);
150 }
151
152 bool test_end(const std::string &str) const
153 {
154 if (end_symbol_ == "NO-END")
155 return false;
156 return end_symbol_ == str;
157 }
158
159 void update_freq(const std::string &str)
160 {
161 ah_domain_error_if(root_ != nullptr) << "Huffman encoding tree has already been generated";
162
163 ah_domain_error_if(test_end(str)) << "End symbol has already been inserted";
164
165 Huffman_Node *huffman_node = nullptr;
166 if (auto huffman_node_ptr = symbol_map_.search(str);
167 huffman_node_ptr == nullptr) // symbol defined previously?
168 { // No ==> create a new entry in symbol_map and insert it into heap
169 std::unique_ptr<BinNode<std::string>> bin_node_auto(new BinNode<std::string>(str));
171 static_cast<Huffman_Node *>(heap_.insert(new Huffman_Node(bin_node_auto.get())));
173 bin_node_auto.release();
174 }
175 else
176 huffman_node = huffman_node_ptr->second; // already defined, retrieve it
177
180 }
181
183 {
184 const size_t symbol_code_size = symbol_code.size();
185 for (size_t i = 0; i < symbol_code_size; ++i)
186 bit_stream.push(symbol_code[i]);
187 }
188
189public:
191 Huffman_Encoder_Engine() : root_(nullptr), freq_root_(nullptr), end_symbol_("NO-END"), text_len_(0)
192 {
193 // empty
194 }
195
201
202private:
203 struct Get_Key
204 {
205 std::string operator () (BinNode<std::string> *p) const noexcept
206 {
207 return is_leaf(p) ? p->get_key() : "";
208 }
209 };
210
211 struct Load_Key
212 {
213 void operator () (BinNode<std::string> *p, std::istream &input) const noexcept
214 {
215 if (is_leaf(p))
216 input >> p->get_key();
217 }
218 };
219
220public:
232 void save_tree(std::ostream &output) const
233 {
234 ah_domain_error_if(root_ == nullptr) << "Huffman tree has not been generated";
235
238 prefix.save(output);
239
241 output << '\n';
242
244 }
245
264 void save_tree_in_array_of_chars(const std::string &array_name, std::ostream &output) const
265 {
266 ah_domain_error_if(root_ == nullptr) << "Huffman tree has not been generated";
267
269 }
270
273 {
274 ah_domain_error_if(root_ == nullptr) << "Huffman tree has not been generated";
275
276 return root_;
277 }
278
292 {
293 ah_domain_error_if(root_ != nullptr) << "Huffman encoding tree has already been generated";
294 ah_domain_error_if(heap_.is_empty()) << "No symbols have been inserted";
295
296 freq_root_ = nullptr;
297
298 while (heap_.size() > 1) // until only one node remains
299 {
303 Huffman_Node *huffman_node = new Huffman_Node(bin_node);
304 LLINK(bin_node) = l_huffman_node->bin_node;
305 RLINK(bin_node) = r_huffman_node->bin_node;
308
309 if (with_freqs)
310 {
311 Freq_Node *&l_freq_node = l_huffman_node->freq_node;
312 if (l_freq_node == nullptr)
313 {
315 l_freq_node->get_key().first = l_huffman_node->bin_node->get_key();
316 l_freq_node->get_key().second = l_huffman_node->get_key();
317 }
318
319 Freq_Node *&r_freq_node = r_huffman_node->freq_node;
320 if (r_freq_node == nullptr)
321 {
323 r_freq_node->get_key().first = r_huffman_node->bin_node->get_key();
324 r_freq_node->get_key().second = r_huffman_node->get_key();
325 }
326
327 const std::string str = std::to_string(new_freq);
328 Freq_Node *&freq_node = huffman_node->freq_node;
329 freq_node = new Freq_Node;
330 freq_node->get_key().first = str;
331 freq_node->get_key().second = huffman_node->get_key();
332 LLINK(freq_node) = l_freq_node;
333 RLINK(freq_node) = r_freq_node;
334 }
335
336 delete l_huffman_node;
337 delete r_huffman_node;
339 } // the remaining node in heap is the prefix tree root
340
342 root_ = huffman_root->bin_node;
343
344 if (with_freqs)
345 freq_root_ = huffman_root->freq_node;
346
347 delete huffman_root;
348 build_encoding_map(); // build code map
349
350 return root_;
351 }
352
379
382 {
383 ah_domain_error_if(freq_root_ == nullptr) << "Huffman tree has not been generated";
384
385 return freq_root_;
386 }
387
397 void set_freq(const std::string &str, const size_t &freq)
398 {
399 ah_domain_error_if(root_ != nullptr) << "Huffman encoding tree has already been generated";
400 ah_domain_error_if(test_end(str)) << "End symbol has already been inserted";
401
402 // Search symbol str
404 if (huffman_node_ptr != nullptr) // already defined?
405 {
406 std::string msg = "Frequency for symbol " + str + " has already set";
407 ah_domain_error() << msg; // Yes ==> this is an error!
408 }
409
410 std::unique_ptr<BinNode<std::string>> bin_node_auto(new BinNode<std::string>(str));
415 bin_node_auto.release();
416 }
417
418private:
419 static const size_t Max_Token_Size = 256;
420
421 static void save_string_as_bytes(const std::string &str, std::ostream &output)
422 {
423 output << str.size() << " ";
424 for (unsigned char c : str)
425 output << static_cast<unsigned int>(c) << " ";
426 }
427
428 static std::string load_string_from_bytes(std::istream &input)
429 {
430 size_t len = 0;
431 input >> len;
432 ah_domain_error_if(not input) << "Malformed Huffman tree stream";
433 ah_domain_error_if(len > Max_Token_Size) << "Symbol too large in Huffman tree stream";
434
435 std::string str;
436 str.resize(len);
437 for (size_t i = 0; i < len; ++i)
438 {
439 unsigned int byte = 0;
440 input >> byte;
441 ah_domain_error_if(not input) << "Malformed Huffman tree stream";
442 ah_domain_error_if(byte > 255u) << "Invalid byte value in Huffman tree stream";
443 str[i] = static_cast<char>(static_cast<unsigned char>(byte));
444 }
445 return str;
446 }
447
449 {
451 return;
452
453 if (is_leaf(p))
454 {
456 output << '\n';
457 return;
458 }
459
462 }
463
465 {
467 return;
468
469 if (is_leaf(p))
470 {
472 return;
473 }
474
477 }
478
479 void insert_end_symbol_node(const std::string &str)
480 {
481 std::unique_ptr<BinNode<std::string>> bin_node_auto(new BinNode<std::string>(str));
482
484 static_cast<Huffman_Node *>(heap_.insert(new Huffman_Node(bin_node_auto.get())));
486 bin_node_auto.release();
487 }
488
490 {
491 while (not heap_.is_empty())
492 {
493 auto *node = static_cast<Huffman_Node *>(heap_.getMin_ne());
494 delete node->bin_node;
495 delete node;
496 }
499 text_len_ = 0;
500 end_symbol_ = "NO-END";
501 }
502
503public:
514 void read_input(char *input, const bool &with_freqs = false)
515 {
516 ah_domain_error_if(root_ != nullptr) << "Huffman encoding tree has already been generated";
517
518 char *curr_stream = input;
520 curr_token[1] = '\0';
521 text_len_ = 0;
522
523 while (*curr_stream != '\0')
524 {
525 curr_token[0] = *curr_stream++;
527 text_len_++;
528 }
529
530 if (end_symbol_ == "NO-END")
532 else if (symbol_map_.search(end_symbol_) == nullptr)
535 }
536
547 void read_input(std::istream &input, const bool &with_freqs = false)
548 {
549 ah_domain_error_if(root_ != nullptr) << "Huffman encoding tree has already been generated";
550
551 char curr_token[2] = {'\0', '\0'};
552 char ch = '\0';
553 text_len_ = 0;
554 while (input.get(ch))
555 {
556 curr_token[0] = ch;
558 ++text_len_;
559 }
560
561 if (end_symbol_ == "NO-END")
563 else if (symbol_map_.search(end_symbol_) == nullptr)
566 }
567
569 void set_end_of_stream(const std::string &str)
570 {
571 ah_domain_error_if(end_symbol_ != "NO-END") << "End symbol has already been inserted";
572
573 ah_domain_error_if(root_ != nullptr) << "Huffman encoding tree has already been generated";
574
575 ah_domain_error_if(symbol_map_.search(str) != nullptr)
576 << "End symbol is already present as a normal symbol";
577
579 end_symbol_ = str;
580 }
581
583 const std::string &get_end_of_stream() const noexcept
584 {
585 return end_symbol_;
586 }
587
599 {
600 ah_domain_error_if(root_ == nullptr) << "Huffman tree has not been generated";
601
602 ah_domain_error_if(end_symbol_ == "NO-END") << "End symbol has not been configured";
603
604 char *curr_stream = input;
606 curr_token[1] = '\0';
607 while (*curr_stream != '\0')
608 {
609 curr_token[0] = *curr_stream++;
611 }
613
614 return bit_stream.size();
615 }
616
627 size_t encode(std::istream &input, BitArray &bit_stream)
628 {
629 ah_domain_error_if(root_ == nullptr) << "Huffman tree has not been generated";
630
631 ah_domain_error_if(end_symbol_ == "NO-END") << "End symbol has not been configured";
632
633 char curr_token[2] = {'\0', '\0'};
634 char ch = '\0';
635 while (input.get(ch))
636 {
637 curr_token[0] = ch;
639 }
640
642 return bit_stream.size();
643 }
644};
645
652{
654 std::string end_symbol;
655
656public:
664 Huffman_Decoder_Engine(BinNode<std::string> *p, const std::string &end) : root(p), end_symbol(end)
665 {
666 // empty
667 }
668
671 {
672 ah_domain_error_if(root == nullptr) << "Huffman tree has not been generated";
673
674 return root;
675 }
676
685 void decode(const BitArray &bit_stream, std::ostream &output) const
686 {
687 const size_t &bit_stream_len = bit_stream.size();
689 for (size_t i = 0; i < bit_stream_len; ++i)
690 {
691 if (bit_stream.read_bit(i) == 0)
692 p = LLINK(p);
693 else
694 p = RLINK(p);
695
696 ah_domain_error_if(p == nullptr) << "Invalid bits sequence";
697
698 if (is_leaf(p)) // leaf?
699 { // yes ==> write symbol and reset to root
700 const std::string &symbol = p->get_key();
701 if (symbol == end_symbol) // end reached?
702 break;
703
704 output << symbol;
705 p = root; // reset to root, a new code will be read
706 }
707 }
708 }
709};
710
711} // end namespace Aleph
712
713#endif // HUFFMAN_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error()
Throws std::domain_error unconditionally.
Definition ah-errors.H:559
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
WeightedDigraph::Node Node
Space-efficient bit array implementation.
Node for binary search tree.
Key & get_key() noexcept
Contiguous array of bits.
Definition bitArray.H:201
void pop()
Removes the last bit of the array.
Definition bitArray.H:468
void load(std::istream &input)
Loads an array of bits from a file.
Definition bitArray.H:602
void push(const unsigned int value)
Inserts the value at the end of the array.
Definition bitArray.H:462
Pair * search(const Key &key) const noexcept
Collect all keys.
Pair * insert(const Key &key, const Data &data)
Insert a key-value pair.
Data & find(const Key &key)
Find the value associated with key.
void empty()
remove all elements from the set
void update(Node *p) noexcept
Updates the priority of a node contained in the heap.
bool is_empty() const noexcept
Node * getMin()
Removes the node with the lowest priority from the heap.
Node * getMin_ne() noexcept
Node * insert(Node *p) noexcept
Inserts a node into a heap.
const size_t & size() const noexcept
BinNode< std::string > * root
Definition Huffman.H:653
Huffman_Decoder_Engine(BinNode< std::string > *p, const std::string &end)
Decoder constructor.
Definition Huffman.H:664
BinNode< std::string > *& get_root()
Returns the root of the Huffman decoding tree.
Definition Huffman.H:670
void decode(const BitArray &bit_stream, std::ostream &output) const
Decode a bit stream.
Definition Huffman.H:685
void insert_end_symbol_node(const std::string &str)
Definition Huffman.H:479
Freq_Node *& get_freq_root()
Returns the root of the frequency tree.
Definition Huffman.H:381
static void save_leaf_keys_in_prefix(BinNode< std::string > *p, std::ostream &output)
Definition Huffman.H:448
void update_freq(const std::string &str)
Definition Huffman.H:159
void save_tree_in_array_of_chars(const std::string &array_name, std::ostream &output) const
Generate C/C++ array declarations for a Huffman tree.
Definition Huffman.H:264
void save_tree(std::ostream &output) const
Save a Huffman tree into a stream.
Definition Huffman.H:232
size_t encode(char *input, BitArray &bit_stream)
Encode the input text.
Definition Huffman.H:598
static std::string load_string_from_bytes(std::istream &input)
Definition Huffman.H:428
void load_tree(std::istream &input)
Load and build a binary tree from a stream.
Definition Huffman.H:363
static const size_t Max_Token_Size
Definition Huffman.H:419
void clear_build_state() noexcept
Definition Huffman.H:489
BinNode< std::string > *& get_root()
Returns the root of the Huffman decoding tree.
Definition Huffman.H:272
void set_freq(const std::string &str, const size_t &freq)
Define the frequency of a symbol.
Definition Huffman.H:397
BinNode< std::string > * root_
Definition Huffman.H:116
static void save_string_as_bytes(const std::string &str, std::ostream &output)
Definition Huffman.H:421
void read_input(char *input, const bool &with_freqs=false)
Read a NUL-terminated character std::string, count frequencies and build the prefix tree.
Definition Huffman.H:514
static void load_leaf_keys_in_prefix(BinNode< std::string > *p, std::istream &input)
Definition Huffman.H:464
void read_input(std::istream &input, const bool &with_freqs=false)
Read a stream, count frequencies and build the prefix tree.
Definition Huffman.H:547
bool test_end(const std::string &str) const
Definition Huffman.H:152
void set_end_of_stream(const std::string &str)
Defines the end-of-stream symbol.
Definition Huffman.H:569
~Huffman_Encoder_Engine()
Destructor - frees all allocated memory.
Definition Huffman.H:197
Huffman_Encoder_Engine()
Encoder constructor.
Definition Huffman.H:191
static void append_code(BitArray &bit_stream, const BitArray &symbol_code)
Definition Huffman.H:182
void build_prefix_encoding(BinNode< std::string > *p, BitArray &array)
Definition Huffman.H:126
const std::string & get_end_of_stream() const noexcept
Return the configured end-of-stream symbol.
Definition Huffman.H:583
size_t encode(std::istream &input, BitArray &bit_stream)
Encode the input text from a stream.
Definition Huffman.H:627
BinNode< std::string > * generate_huffman_tree(const bool &with_freqs=false)
Generate the Huffman prefix tree.
Definition Huffman.H:291
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
void tree_to_bits(Node *root, BitArray &array)
Compute a bit code for the binary tree.
void destroyRec(Node *&root) noexcept
Free recursively all the memory occupied by the tree root
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
BinNode< std::pair< std::string, size_t > > Freq_Node
Definition Huffman.H:61
BinHeap< size_t > Huffman_Heap
Definition Huffman.H:86
and
Check uniqueness with explicit hash + equality functors.
DynMapTree< std::string, BitArray, Treap_Vtl > Code_Map
Definition Huffman.H:103
static void increase_freq(Huffman_Node *huffman_node) noexcept
Definition Huffman.H:93
static void prefix(Node *root, DynList< Node * > &acc)
static const size_t & get_freq(Huffman_Node *huffman_node) noexcept
Definition Huffman.H:88
static bool is_leaf(BinNode< std::string > *p) noexcept
Definition Huffman.H:104
static void set_freq(Huffman_Node *huffman_node, const size_t &freq) noexcept
Definition Huffman.H:98
Node heap without virtual destructor.
std::string operator()(BinNode< std::string > *p) const noexcept
Definition Huffman.H:205
void operator()(BinNode< std::string > *p, std::istream &input) const noexcept
Definition Huffman.H:213
Huffman_Node(BinNode< std::string > *node)
Definition Huffman.H:75
BinNode< std::string > * bin_node
Definition Huffman.H:65
Freq_Node * freq_node
Definition Huffman.H:67
#define RLINK(i, n)
#define LLINK(i, n)
Binary heap implementation using tree structure.
Utility functions for binary tree operations.
Dynamic key-value map based on balanced binary search trees.
Treap: randomized BST combining tree and heap properties.
ofstream output
Definition writeHeap.C:215