LTOList
|
LTOList (Logarithmic-Time-Operation List) is a linear list structure using a binary search tree. This is an implementation of LTOList in C++.
The variable-length array (VLA, std::vector
in C++) and the linked list (LL, std::list
in C++) are famous linear list structures, whose computational costs are: (n: the size of the list)
The question is that how we achieve the middle; LTOList achieves O(log n) time for all of a random access, an insertion and a deletion in the worst case!
An LTOList is implemented with a binary search tree (BST) where the number of children is kept for each tree node. In the library a "red-black tree" is implemented from scratch.
Such a data structure seems to be known to many others, but I could not find a specific name.
If you know a specific name, please tell me.
Since O(log n) time is achieved by tree operations (namely, pointer operations), in reality insertions and deletions may be slower than those for VLA that theoretically requires O(n) time but much more memory-efficient.
The implementation of LTOList is based on BST, but more memory-consuming than ordinary BST that orders elements automatically: ordinary BST requires three pointers for each list element, while LTOList requires five.
std::map
?
How do we achieve O(log n) time for all of a random access, an insertion and a deletion in the worst case?
First suppose that, for each node in BST, we write the index of the element. However, when we insert or delete an element, the updates of the indices require O(n) time, as an insertion or deletion for VLA requires.
To avoid this situation, for each node in BST, we write the numbers of left and right children. Then, when we insert or delete an element, the updates of the numbers require only O(log n) time; it is sufficient to update the numbers for only the nodes from the inserted or deleted nodes to the root node.
LTOList has similar APIs to those of std::vector
; almost all APIs are implemented except for memory allocations (e.g., std::vector<T>::reserve
).
A large difference from std::vector
is that, since LTOList is implemented as a BST, given an iterator we can insert another element either before or after the iterator.
You can build examples by the following command (example for LTOList_example_poppush.cpp
, using GCC):
You can also create a Makefile
that builds examples by CMake: if you have CMake, the following command will generate a Makefile
for all examples:
The document can be generated with Doxygen. (Not all APIs are documented yet.)
The generated document is also available at https://hhiro.net/ltolist/doxygen/ .
H.Hiro
Published under the MIT license. See LICENSE.txt for details.