Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
huffman_btreepic.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
32
92#ifndef HUFFMAN_BTREEPIC_H
93#define HUFFMAN_BTREEPIC_H
94
95#include <cstdlib>
96#include <ostream>
97#include <algorithm>
98#include <tpl_dynMapTree.H>
99#include <Huffman.H>
100
113
122{
123 int pos = 0;
124 int level = 0;
126
129
135 Infix_Desc(int i, int l) : pos(i), level(l), offset(NO_OFFSET) {}
136};
137
146{
147 bool is_left = false;
148 Freq_Node * level_succ = nullptr;
149
151 Level_Desc() = default;
152
158 Level_Desc(bool il, Freq_Node * succ = nullptr)
159 : is_left(il), level_succ(succ) {}
160};
161
164
165// ============================================================================
166// Global state (module-level, not thread-safe)
167// ============================================================================
168
171
174
176inline std::ostream * output_ptr = nullptr;
177
179inline Freq_Node * pred = nullptr;
180
182inline int minimal_gap = 4;
183
185inline constexpr size_t MAX_OFFSET_INDEX = 7;
186
188inline const long double offset[] = { 10, 15, 25, 40, 55, 65, 85, 90 };
189
195[[nodiscard]] inline long double get_offset(size_t index) noexcept
196{
197 return offset[std::min(index, MAX_OFFSET_INDEX)];
198}
199
207{
210 pred = nullptr;
211}
212
213// ============================================================================
214// Traversal callback functions
215// ============================================================================
216
227inline void save_infix_pos(Freq_Node * p, int level, int pos)
228{
229 infix_table.insert(p, Infix_Desc(pos, level));
230}
231
242inline void save_level_pos_1(Freq_Node * p, int pos, bool is_left)
243{
244 (void)pos;
245 level_table.insert(p, Level_Desc(is_left));
246}
247
258inline void save_level_pos_2(Freq_Node * p, int pos, bool is_left)
259{
260 (void)is_left;
261
262 if (pos == 0)
263 {
264 assert(pred == nullptr);
265 pred = p;
266 return;
267 }
268
269 assert(pred != nullptr and pred != p);
270
272 level_desc_pred.level_succ = p;
273 pred = p;
274}
275
286inline void write_prefix(Freq_Node * p, int level, int prefix_pos)
287{
288 (void)level;
290
291 const Infix_Desc & infix_desc = infix_table[p];
293}
294
305inline void write_freq(Freq_Node * p, int level, int pos)
306{
307 (void)level;
308 (void)pos;
309
310 const size_t & freq = p->get_key().second;
311 *output_ptr << "\"" << freq << "\" ";
312}
313
325inline void write_leaves(Freq_Node * p, int level, int pos)
326{
327 (void)level;
328
329 // Only process leaf nodes
330 if (not (LLINK(p) == nullptr and RLINK(p) == nullptr))
331 return;
332
333 const std::string & key = p->get_key().first;
334
335 *output_ptr << "TAG " << pos << " \"";
336
337 // Escape special LaTeX characters
338 if (key == "\n")
339 *output_ptr << "$\\backslash$n";
340 else if (key == "")
341 *output_ptr << "$\\neg$";
342 else if (key == "$")
343 *output_ptr << "\\$";
344 else if (key == "&")
345 *output_ptr << "\\&";
346 else if (key == "#")
347 *output_ptr << "\\#";
348 else if (key == "%")
349 *output_ptr << "\\%";
350 else if (key == "{")
351 *output_ptr << "$\\{$";
352 else if (key == "}")
353 *output_ptr << "$\\}$";
354 else if (key == "^")
355 *output_ptr << "\\^";
356 else if (key == "_")
357 *output_ptr << "\\_";
358 else if (key == "\\")
359 *output_ptr << "$\\backslash$";
360 else if (key == " ")
361 *output_ptr << "$\\square$";
362 else if (key == "\"")
363 *output_ptr << "$\\prime\\prime$";
364 else
365 *output_ptr << key;
366
367 *output_ptr << "\" S 0 -20 " << std::endl;
368}
369
375[[nodiscard]] inline size_t num_digits(const int & n)
376{
377 return std::to_string(n).size();
378}
379
391inline void adjust_nodes(Freq_Node * p, int p_level, int p_infix_pos)
392{
393 // Last node has no successor to check
394 if (static_cast<size_t>(p_infix_pos) == level_table.size() - 1)
395 return;
396
398 Freq_Node *& p_succ = p_level_desc.level_succ;
399
400 // No successor in level-order?
401 if (p_succ == nullptr)
402 return;
403
405
406 // Not at the same level?
407 if (p_level != p_succ_infix_desc.level)
408 return;
409
410 const int & p_succ_infix_pos = p_succ_infix_desc.pos;
411
412 // Separation in nodes between the two
414
415 // Sufficiently separated?
416 if (diff_pos > minimal_gap)
417 return;
418
420
421 // Same orientation (both left or both right children)?
422 if (p_suc_level_desc.is_left == p_level_desc.is_left)
423 return;
424
426
427 const std::string & kp = p->get_key().first;
428 const size_t kp_sz = kp.size();
429
430 // Apply left offset to current node if not already offset
431 if (p_infix_desc.offset == NO_OFFSET)
432 {
433 *output_ptr << "xoffset " << p_infix_pos << " "
434 << -get_offset(kp_sz) << std::endl;
435 p_infix_desc.offset = LEFT;
436 }
437
439
440 const std::string & k_succ = p_succ->get_key().first;
441 const size_t k_succ_sz = k_succ.size();
442
443 // Apply right offset to successor
444 *output_ptr << "xoffset " << p_succ_infix_pos << " "
445 << static_cast<int>(get_offset(k_succ_sz) / 2) << std::endl;
446
447 p_succ_infix_desc.offset = RIGHT;
448}
449
450// ============================================================================
451// Main API
452// ============================================================================
453
476inline void huffman_to_btreepic(Freq_Node * p, const bool with_level_adjust = false)
477{
478 if (p == nullptr or output_ptr == nullptr)
479 return;
480
481 // Reset state for new tree
483
484 // First pass: record infix positions
486
487 // Write tree structure in prefix order
488 *output_ptr << "start-prefix ";
490 *output_ptr << std::endl << "start-key ";
491
492 // Write frequency labels
494 *output_ptr << std::endl;
495
496 // Write leaf node tags
498 *output_ptr << std::endl;
499
501 return;
502
503 // Level adjustment: two passes for linking successors
506
507 // Final pass: adjust overlapping labels
509}
510
524 std::ostream & output,
525 bool with_level_adjust = false)
526{
529}
530
531#endif // HUFFMAN_BTREEPIC_H
Huffman coding for data compression.
Node for binary search tree.
Key & get_key() noexcept
void empty() noexcept
empty the list
Definition htlist.H:1689
Generic key-value map implemented on top of a binary search tree.
Pair * insert(const Key &key, const Data &data)
Insert a key-value pair.
Data & find(const Key &key)
Find the value associated with key.
const size_t & size() const
Returns the cardinality of the set.
void empty()
remove all elements from the set
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
int preOrderRec(Node *root, void(*visitFct)(Node *, int, int))
Traverse recursively in preorder a binary tree.
constexpr Node *& RLINK(Node *p) noexcept
Return the right tree of p.
void levelOrder(Node *root, void(*visitFct)(Node *, int, bool))
Traverse a binary tree by levels.
int inOrderRec(Node *root, void(*visitFct)(Node *, int, int))
Traverse recursively inorder a binary tree.
constexpr Node *& LLINK(Node *p) noexcept
Return a pointer to left subtree.
void reset_huffman_btreepic_state() noexcept
Reset global state for a new tree processing.
Freq_Node * pred
Predecessor node in level-order traversal.
void write_freq(Freq_Node *p, int level, int pos)
Write node frequency value.
void save_level_pos_1(Freq_Node *p, int pos, bool is_left)
First pass level-order callback: record child direction.
long double get_offset(size_t index) noexcept
Get safe offset value with bounds checking.
void adjust_nodes(Freq_Node *p, int p_level, int p_infix_pos)
Adjust node positions to prevent label overlap.
void write_prefix(Freq_Node *p, int level, int prefix_pos)
Write node position in prefix order.
Offset
Horizontal offset direction for node label adjustment.
@ NO_OFFSET
No offset applied.
@ LEFT
Shifted to the left.
@ RIGHT
Shifted to the right.
size_t num_digits(const int &n)
Compute number of decimal digits in an integer.
DynMapTree< Freq_Node *, Infix_Desc, Treap > infix_table
Map from node pointer to infix position descriptor.
int minimal_gap
Minimum gap (in nodes) before applying offset adjustment.
void huffman_to_btreepic(Freq_Node *p, const bool with_level_adjust=false)
Generate btreepic specification for a Huffman tree.
std::ostream * output_ptr
Output stream pointer for btreepic commands.
constexpr size_t MAX_OFFSET_INDEX
Maximum valid index for offset array.
const long double offset[]
Offset values indexed by symbol string length (bounded by MAX_OFFSET_INDEX)
Level_Table level_table
Map from node pointer to level traversal descriptor.
void save_level_pos_2(Freq_Node *p, int pos, bool is_left)
Second pass level-order callback: link successors.
void save_infix_pos(Freq_Node *p, int level, int pos)
Save infix position for a node.
void write_leaves(Freq_Node *p, int level, int pos)
Write leaf node labels with LaTeX escaping.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Descriptor for infix (in-order) traversal position.
Offset offset
Applied offset direction.
int level
Tree level (0 = root)
Infix_Desc()
Default constructor.
int pos
In-order position (0-based)
Infix_Desc(int i, int l)
Construct with position and level.
Descriptor for level-order traversal information.
Level_Desc(bool il, Freq_Node *succ=nullptr)
Construct with child direction and optional successor.
bool is_left
True if this node is a left child.
Level_Desc()=default
Default constructor.
Freq_Node * level_succ
Next node in level-order traversal.
Dynamic key-value map based on balanced binary search trees.
DynList< int > l
ofstream output
Definition writeHeap.C:213