|
Zip and Skip Tries
|
Implements a skip list data structure optimized for storing and retrieving BitString keys.
More...
#include <SkipTrie.hpp>

Classes | |
| struct | EqualOrSuccessor |
| Helper struct to return a Node pointer, a flag indicating equality, and an LCP value. More... | |
| class | Iterator |
| Provides forward/backward iteration over the keys in the base level of the SkipTrie. More... | |
| struct | Node |
| Represents a single node within the SkipTrie structure. More... | |
| struct | NodeLCP |
| Helper struct to return a Node pointer and an associated LCP value. More... | |
| struct | ResultLCP |
| Helper struct to return a comparison result (ordering) and an LCP value. More... | |
Public Types | |
| using | KEY_T = BitString< CHAR_T, CHAR_SIZE_BITS > |
Alias for the key type used in the SkipTrie, based on BitString. | |
Public Member Functions | |
| SkipTrie () | |
| Constructs an empty SkipTrie. | |
| bool | insert (const KEY_T *key) noexcept |
| Inserts a new key into the skip list with a randomly generated height. | |
| bool | insert (const KEY_T *key, size_t height) noexcept |
| Inserts a new key into the skip list with a specified height. | |
| bool | contains (const KEY_T *key) const noexcept |
| Checks if a specific key exists within the skip list. | |
| bool | remove (const KEY_T *key) noexcept |
| Removes a key from the skip list. | |
| std::ostream & | print (std::ostream &os) const noexcept |
| Prints a textual representation of the skip list structure, layer by layer, to an output stream. | |
| std::string | to_string () const noexcept |
| Generates a string representation of the skip list structure. | |
| size_t | size () const noexcept |
| Returns the number of keys currently stored in the skip list. | |
| size_t | height () const noexcept |
| Returns the current maximum height of the skip list. | |
| size_t | lcp (const KEY_T *key) const noexcept |
| Calculates the Longest Common Prefix (LCP) between a given key and its position in the skip list search path. | |
| size_t | lcp_with_others (const KEY_T *key) const noexcept |
| Calculates the maximum Longest Common Prefix (LCP) between a given key and its immediate neighbors (predecessor and successor) at the base level. | |
| std::vector< const KEY_T * > | suffix_search (const KEY_T *key) const noexcept |
| Finds all keys in the skip list that have the given key as a prefix. | |
| std::vector< const KEY_T * > | range_search (const KEY_T *key1, const KEY_T *key2) const noexcept |
| Finds all keys within a specified lexicographical range [key1, key2). | |
| std::unordered_map< size_t, size_t > | get_lcp_group_sizes () const noexcept |
| Calculates the sizes of groups of consecutive nodes sharing the same LCP value at the base level. | |
| Iterator | begin () const noexcept |
| Returns an iterator pointing to the first key in the skip list (at the base level). | |
| Iterator | end () const noexcept |
| Returns an iterator pointing past the last key in the skip list (the tail sentinel at the base level). | |
Static Public Member Functions | |
| static size_t | get_random_height () |
| Generates a random height for a new node based on a geometric distribution. | |
Protected Member Functions | |
| void | add_layer () noexcept |
| Adds a new, empty layer on top of the current skip list structure. | |
| void | remove_layer () noexcept |
| Removes the top-most layer of the skip list if it is empty (contains only sentinels). | |
| std::shared_ptr< Node > | insert_recursive (const KEY_T *key, Node *curr, size_t height, Direction direction, size_t lcp, size_t current_height) noexcept |
| Recursively finds the correct position and inserts links for a new node at a specific level and below. | |
| Direction | iter_layer (const KEY_T *key, Node *&curr, Direction direction, size_t &lcp) const noexcept |
| Iterates horizontally along a single layer to find the node preceding the insertion/search point for a given key. | |
| virtual NodeLCP | find_first (const KEY_T *key, const bool require_level0=false) const noexcept |
| Finds the node containing the exact key, returning the node and the search path LCP. | |
| virtual EqualOrSuccessor | find_equal_or_successor (const KEY_T *key, const bool require_level0) const noexcept |
| Finds the node containing the exact key or its immediate successor. | |
| virtual ResultLCP | compare (const KEY_T *key1, const KEY_T *key2, size_t lcp) const noexcept |
| Compares two keys starting from a known common prefix length. | |
Protected Attributes | |
| size_t | m_size |
| Stores the total number of keys (nodes) in the base level of the skip list. | |
| size_t | m_height |
| Stores the current maximum height (number of levels) of the skip list. | |
| std::shared_ptr< Node > | m_head = nullptr |
| Shared pointer to the head sentinel node of the top-most layer. | |
| std::shared_ptr< Node > | m_lower_head = nullptr |
| Shared pointer to the head sentinel node of the base layer (level 0). | |
| std::shared_ptr< Node > | m_lower_tail = nullptr |
| Shared pointer to the tail sentinel node of the base layer (level 0). | |
Related Symbols | |
(Note that these are not member symbols.) | |
| template<typename CHAR_T , unsigned CHAR_SIZE_BITS> | |
| std::ostream & | operator<< (std::ostream &os, const SkipTrie< CHAR_T, CHAR_SIZE_BITS > &ssl) |
Overload of the stream insertion operator (<<) for SkipTrie. | |
Implements a skip list data structure optimized for storing and retrieving BitString keys.
This class uses a multi-level linked list (skip list) structure to store keys. Each node can have connections to the next/previous node on the same level and a connection to a corresponding node on the level below. Random heights are assigned to nodes upon insertion to maintain probabilistic balance, aiming for logarithmic average time complexity for search, insertion, and deletion. The structure leverages Longest Common Prefix (LCP) information stored between adjacent nodes to speed up comparisons during traversal.
| CHAR_T | The underlying character type used in the keys (BitString). |
| CHAR_SIZE_BITS | The number of significant bits per character in CHAR_T. Defaults to sizeof(CHAR_T) * 8. |
Definition at line 53 of file SkipTrie.hpp.
| using SkipTrie< CHAR_T, CHAR_SIZE_BITS >::KEY_T = BitString<CHAR_T, CHAR_SIZE_BITS> |
Alias for the key type used in the SkipTrie, based on BitString.
Definition at line 57 of file SkipTrie.hpp.
| SkipTrie< CHAR_T, CHAR_SIZE_BITS >::SkipTrie | ( | ) |
Constructs an empty SkipTrie.
Initializes the size and height to zero. Head and tail pointers are initially null. Layers are added dynamically as needed during insertion.
Definition at line 571 of file SkipTrie.hpp.
|
protectednoexcept |
Adds a new, empty layer on top of the current skip list structure.
Creates new head and tail sentinel nodes for the new top layer. Links the new head's down pointer to the old head and the new tail's down pointer to the old tail. Updates m_head and increments m_height. Initializes m_lower_head and m_lower_tail if this is the first layer being added.
insert when a node's random height exceeds the current maximum height. Definition at line 590 of file SkipTrie.hpp.
|
noexcept |
Returns an iterator pointing to the first key in the skip list (at the base level).
Definition at line 529 of file SkipTrie.hpp.
|
protectedvirtualnoexcept |
Compares two keys starting from a known common prefix length.
Performs a sequential comparison of key1 and key2, assuming the first lcp characters are identical. Uses BitString::seq_k_compare for the actual comparison.
| key1 | Pointer to the first BitString key. |
| key2 | Pointer to the second BitString key. |
| lcp | The length of the known common prefix (in characters) from which to start the comparison. |
std::strong_ordering) and the total LCP length found. ParallelSkipTrie). Reimplemented in ParallelSkipTrie< CHAR_T, CHAR_SIZE_BITS >.
Definition at line 638 of file SkipTrie.hpp.
Checks if a specific key exists within the skip list.
Uses find_first to locate the key.
| key | A pointer to the BitString key to search for. |
Definition at line 726 of file SkipTrie.hpp.
|
noexcept |
Returns an iterator pointing past the last key in the skip list (the tail sentinel at the base level).
Definition at line 536 of file SkipTrie.hpp.
|
protectedvirtualnoexcept |
Finds the node containing the exact key or its immediate successor.
Traverses the skip list from the top layer down, using iter_layer at each level to narrow down the position. Returns the node found (either the exact match or the first node lexicographically greater than the key) and indicates whether an exact match was found. Also returns the LCP computed along the search path.
| key | A pointer to the BitString key to search for. |
| require_level0 | If true, ensures the search descends fully to level 0 before returning the node. Defaults to false. |
contains, insert, remove, etc. Reimplemented in ParallelSkipTrie< CHAR_T, CHAR_SIZE_BITS >.
Definition at line 922 of file SkipTrie.hpp.
|
protectedvirtualnoexcept |
Finds the node containing the exact key, returning the node and the search path LCP.
Uses find_equal_or_successor to perform the search. If the key is found (is_equal is true), returns the node and LCP. Otherwise, returns nullptr for the node.
| key | A pointer to the BitString key to find. |
| require_level0 | If true, ensures the returned node (if found) is from the base level (level 0). Defaults to false. |
nullptr) and the LCP computed during the search. Definition at line 716 of file SkipTrie.hpp.
|
noexcept |
Calculates the sizes of groups of consecutive nodes sharing the same LCP value at the base level.
Iterates through the base level of the skip list, tracking changes in LCP values between adjacent nodes. Uses a stack-like approach to determine the extent (size) of consecutive nodes that share a common LCP value greater than or equal to the LCP values of surrounding nodes.
Definition at line 989 of file SkipTrie.hpp.
|
static |
Generates a random height for a new node based on a geometric distribution.
The height determines how many levels the new node will participate in. Uses a static random number generator (geometric distribution with p=0.5).
Definition at line 577 of file SkipTrie.hpp.
|
inlinenoexcept |
Returns the current maximum height of the skip list.
The height is the number of levels in the skip list (0-indexed). An empty list has height 0 (after first insertion, height becomes >= 1).
Definition at line 150 of file SkipTrie.hpp.
Inserts a new key into the skip list with a randomly generated height.
Calls get_random_height() to determine the height and then calls the height-specific insert method.
key must exceed the lifetime of the SkipTrie. Definition at line 733 of file SkipTrie.hpp.
Inserts a new key into the skip list with a specified height.
Adds necessary layers if the specified height exceeds the current maximum height. Then, calls the recursive insertion helper function to place the node at the correct position across all levels up to the specified height. Increments the size if insertion is successful.
| key | A pointer to the BitString key to insert. The SkipTrie stores this pointer directly. |
| height | The height (number of levels above the base) for the new node. |
key must exceed the lifetime of the SkipTrie. Definition at line 740 of file SkipTrie.hpp.
|
protectednoexcept |
Recursively finds the correct position and inserts links for a new node at a specific level and below.
Traverses the current level (current_height) using iter_layer to find the predecessor node (curr) for the key. Recursively calls itself for the level below (current_height - 1). If the insertion height matches the current_height, it creates the new node at this level, links it between curr and curr->next, sets its down pointer to the node returned by the recursive call (or null at base level), and updates LCP values.
| key | A pointer to the BitString key being inserted. |
| curr | The starting node for traversal at the current level. |
| height | The target insertion height for the new node (determines up to which level it's inserted). |
| direction | The initial traversal direction inherited from the level above. |
| lcp | The LCP length calculated so far along the search path from the level above. |
| current_height | The current level being processed in the recursion (starts from m_height - 1). |
nullptr if the key already existed or if current_height is above the target height. This pointer is used to link the down pointer from the level above. Definition at line 765 of file SkipTrie.hpp.
|
protectednoexcept |
Iterates horizontally along a single layer to find the node preceding the insertion/search point for a given key.
Starts from curr and moves in the specified direction. Compares the key with the keys of subsequent nodes, using LCP values for optimization. Updates curr to point to the immediate predecessor of the key's position on this layer. Updates the lcp parameter with the LCP value computed during the final relevant comparison.
| key | A pointer to the BitString key being searched for or inserted. | |
| [in,out] | curr | A reference to the pointer to the current node. Updated by the function to the predecessor node. |
| direction | The initial traversal direction (usually FORWARD or BACKWARD inherited from the level above). | |
| [in,out] | lcp | A reference to the LCP length calculated so far. Updated by the function. |
FORWARD or BACKWARD), or INPLACE if the exact key was found. Definition at line 646 of file SkipTrie.hpp.
Calculates the Longest Common Prefix (LCP) between a given key and its position in the skip list search path.
Performs a search (find_first) for the key and returns the LCP value computed during that search. If the key is found, this LCP is typically the full length of the key. If not found, it's the LCP with the path leading to the insertion point.
| key | A pointer to the BitString key. |
Definition at line 878 of file SkipTrie.hpp.
Calculates the maximum Longest Common Prefix (LCP) between a given key and its immediate neighbors (predecessor and successor) at the base level.
Finds the node for the key (or its successor if not present) using find_first at level 0. Returns the maximum of the LCP with the next node and the LCP with the previous node at the base level. If the key is not found, it returns the LCP computed during the search for its potential position.
| key | A pointer to the BitString key. |
Definition at line 885 of file SkipTrie.hpp.
|
noexcept |
Prints a textual representation of the skip list structure, layer by layer, to an output stream.
Traverses each layer from head to tail, printing node keys and the LCP values between adjacent nodes. Useful for debugging and visualizing the structure.
| os | The output stream (e.g., std::cout) to write the representation to. |
os for chaining. Definition at line 1038 of file SkipTrie.hpp.
|
noexcept |
Finds all keys within a specified lexicographical range [key1, key2).
Locates the starting node (equal to or successor of key1) using find_equal_or_successor. Locates the ending node (equal to or successor of key2). Iterates forward from the start node up to (but not including) the end node at the base level, collecting pointers to the keys.
| key1 | A pointer to the BitString representing the lower bound of the range (inclusive). |
| key2 | A pointer to the BitString representing the upper bound of the range (exclusive). |
Definition at line 960 of file SkipTrie.hpp.
Removes a key from the skip list.
Finds the node containing the key using find_first. If found, removes the node and its corresponding nodes on all levels below it by adjusting pointers. Decrements the size. Removes empty top layers if necessary.
| key | A pointer to the BitString key to remove. |
Definition at line 839 of file SkipTrie.hpp.
|
protectednoexcept |
Removes the top-most layer of the skip list if it is empty (contains only sentinels).
Updates m_head to point to the head of the layer below and decrements m_height. Resets m_lower_head and m_lower_tail if the height becomes zero.
remove to potentially shrink the skip list height after deletions. Definition at line 622 of file SkipTrie.hpp.
|
inlinenoexcept |
Returns the number of keys currently stored in the skip list.
Definition at line 142 of file SkipTrie.hpp.
|
noexcept |
Finds all keys in the skip list that have the given key as a prefix.
Performs a search (find_equal_or_successor) to locate the first potential match. If the LCP at that point equals the length of the input key, it iterates forward through the base level as long as the LCP between adjacent nodes is greater than or equal to the input key's length, collecting all matching keys.
| key | A pointer to the BitString representing the prefix to search for. |
key as a prefix. Returns an empty vector if no such keys are found. Definition at line 898 of file SkipTrie.hpp.
|
noexcept |
Generates a string representation of the skip list structure.
Similar to print, but captures the output into a std::string.
Definition at line 1065 of file SkipTrie.hpp.
|
related |
Overload of the stream insertion operator (<<) for SkipTrie.
Allows printing a SkipTrie object directly to an output stream using os << skipTrie;. Delegates the actual printing logic to the SkipTrie::print method.
| CHAR_T | The character type of the keys. |
| CHAR_SIZE_BITS | The number of significant bits per character. |
| os | The output stream (e.g., std::cout). |
| ssl | The SkipTrie object to print. |
os. Definition at line 1032 of file SkipTrie.hpp.
|
protected |
Shared pointer to the head sentinel node of the top-most layer.
Definition at line 252 of file SkipTrie.hpp.
|
protected |
Stores the current maximum height (number of levels) of the skip list.
Definition at line 215 of file SkipTrie.hpp.
|
protected |
Shared pointer to the head sentinel node of the base layer (level 0).
Definition at line 254 of file SkipTrie.hpp.
|
protected |
Shared pointer to the tail sentinel node of the base layer (level 0).
Definition at line 256 of file SkipTrie.hpp.
|
protected |
Stores the total number of keys (nodes) in the base level of the skip list.
Definition at line 213 of file SkipTrie.hpp.