Weak Binary Search Trees
Abstract
Binary Search Trees (BST) have probably been studied more extensively than any other data structure in computer science. Their central property is the in-order invariant, which enables search for a key in time proportional to the height of the tree. Quite interestingly, the need for this strict invariant for efficient search seems to have always been taken for granted. In this paper, we introduce Weak Binary Search Trees (WST) and show that the in-order invariant can be relaxed substantially without sacrificing the runtime bounds for search known from BST.
We provide a simple and efficient search algorithm and list methods for insertion and deletion of keys in time proportional to the height of the tree. For balancing WST, rotations are less efficient than in BST. We adapt a rotation-free balancing scheme to WST, which can keep update operations in overall time in the amortized average case.
Keywords and phrases:
Binary search trees, weak data structures, relaxed in-order invariant, balancing2012 ACM Subject Classification:
Theory of computation Data structures design and analysisAcknowledgements:
Thanks are going to the anonymous reviewers for helpful comments and suggestions.Editor:
John IaconoSeries and Publisher:
Leibniz International Proceedings in Informatics, Schloss Dagstuhl – Leibniz-Zentrum für Informatik
1 Introduction
What happens if a data structure is bereft of a major part of its central invariant? How much of the properties of a structure can be broken until it loses the capabilities it was designed for?
“Weak” variants of data structures are an interesting field of study, as they relax the conditions imposed on the shape or arrangement of their components, while trying to maintain the efficiency of the typical operations working on those structures. Often, a higher degree of freedom is achieved by such a modification. A well-known example is the weak heap [5] where – in contrast to a standard heap-ordered array or tree – only one of the successors of an element (rather than both) must satisfy the heap condition. It turns out that standard heap operations enjoy the same asymptotic bounds in a weak heap as in a regular heap, while some special operations, such as merging two heaps, are even easier to achieve.
Binary Search Trees (BST) are among the best-known and fundamental data structures in computer science. They have been studied extensively and form the base of many advanced and more complex data structures. An abundance of research has been produced on how those trees can most efficiently be represented in memory, how the relevant dictionary operations such as lookup, insertion and deletion can be performed with as little instructional overhead as possible, pushing the constant factors of these operations ever closer to their theoretical limits. Intricate methods of (re-)balancing have been proposed to achieve logarithmic tree height while ensuring that the chief property of search trees, the in-order invariant, is restored after each change. This invariant is central to search trees and its necessity seems so self-evident that little to no research can be found on whether it might be possible to maintain efficient lookup and update capabilities without strictly adhering to it.
The research presented here explores how the in-order invariant of simple, non-augmented binary search trees can be relaxed substantially without losing the capability to look up, insert and delete keys in time, where is the height of the tree. We call the resulting data structure a weak binary search tree (WST). We also outline how to balance WST, yielding worst-case time for search and expected amortized times for update operations, where is the number of elements stored in the tree.
The search algorithm we present for WST is simple, instructive and entertaining. While the main result may seem mainly of theoretical interest, it can also be relevant in practice, as it facilitates the development of more complex data structures. Tree nodes are often augmented with further information and are thus subject to additional invariants that might be hard to maintain together with the in-order invariant. We are hopeful that practical applications will turn up in time and encourage the reader to come up with some.
2 Preliminaries
2.1 Binary Search Trees
Traditionally, a binary search tree (BST) is a binary tree with the following property, known as in-order invariant:
For each node in , all keys stored in the left subtree of are less than the key stored in , and all keys stored in the right subtree of are greater than the key stored in . (Throughout this paper, we assume that all keys are distinct.)
This property allows a search algorithm to use the key in each node as a router, (or, pivot) to direct the search, i.e. to decide the subtree in which the search is continued. A simple, iterative lookup procedure is given in Algorithm 1.
The search can be imagined like a “probe” traveling down one path in the tree by following one child pointer on each level. Clearly, plays a crucial part in the algorithm, as it is not only a data element but also serves as a split key or router for the lookup process. One main question this paper addresses is whether the search for can be directed efficiently without or any augmented field in acting as a split key.
2.2 Background and Related Work
Weak variants of data structures have been proposed especially in the context of heaps. Dutton uses weak heaps to improve heap sort [5]. Hinze introduced semi-heaps to implement priority search queues [8].
Binary search trees are among the earliest and most basic data structures and are covered in virtually every introductory computer science textbook. Research on the topic has been going on for more than 60 years, and countless data structures have evolved from BST or been built upon them. A comprehensive overview would be far beyond the scope of this paper and is not required as background for our work. For balanced trees, very good overviews are provided in [2] and [9].
Despite the abundance of research on search trees, surprisingly little work can be found about whether and how the in-order invariant can be modified or relaxed without breaking the complexity bounds of standard search tree operations. To the best of our knowledge, the only published research related to the topic was done by De et al. in their work on an “in-place” version of priority search trees [3][4]. They propose an array-based structure supporting certain 2D range queries on point sets, and requiring only extra memory for construction from an input array. In some of their range query algorithms, the authors use a similar dual-probing approach as we do.
3 Weak Binary Search Trees
3.1 Relaxing the in-order invariant
We define weak binary search trees as follows:
Definition 1.
A binary tree is called a weak binary search tree (WST) if for each node in , all keys stored in the left subtree of are smaller than all keys stored in the right subtree of .
Notice that no condition is imposed on the key stored in itself. Hence, the tree shown in Figure 1 is a WST, but not a BST. (Since the strict in-order invariant of BSTs obviously satisfies the weaker invariant, any BST is of course also a WST.)
3.2 Properties of WST
We observe that the relaxed invariant still ensures that all keys stored on the same tree level are in ascending order from left to right. This follows directly from the WST invariant. However, a WST loses the ability to produce a sorted list of all keys by an in-order (i.e. depth-first) traversal of the tree. In addition, the key stored in a node cannot be used as a split key in order to direct the further search.
Hence, it may seem that efficient search is not possible because in the worst case a search algorithm will always need to visit both subtrees of , effectively increasing the number of inspected nodes on each level. This point is also typically made in adversary arguments put forward by large language models (LLMs) when presented with the definition of the WST data structure and asked about efficient search in it. We invite the reader to stop and think about why this argument is insufficient, and to try and find an efficient search algorithm.
4 Efficient Search in WST
As the in-order invariant does not hold in WST, we cannot rely on the key of the currently visited node to exclude one whole subtree from further search. Instead, it may be necessary to inspect both children of . While this might suggest an uncontrollable inflation of the number of inspected nodes, that is not necessarily the case: as long as it is possible to bound the number of nodes visited per level by a constant, we can keep the overall search cost in . In fact, we will show that the WST invariant is strong enough to exclude all but two nodes on each level from further inspection. All we need to do is abandon the restricted focus on a single pointer traveling down a search path. Instead, we use a pair of pointers descending the tree together on a “two-lane” path.
4.1 Stay in sight
In order to explain our search in a WST, we introduce the following binary relation among nodes in a tree.
Definition 2.
Let and be nodes in a binary tree . We say that is in sight of (short: ) if
-
(1)
and are on the same level in and
-
(2)
there are no other nodes between and on that level.
It follows from the definition that the in-sight relation is symmetric, i.e. . We can therefore also say that two nodes and are, or are not, in sight (of each other). It also follows straight from the definition that the relation is reflexive: .
Obviously, any two sibling nodes in a binary tree are in sight of each other. In addition, nodes down on deeper levels of neighbouring subtrees can be in sight of each other. In Figure 1, the two grandchildren of the root with keys and are in sight of each other, as are those with keys and . Furthermore, two nodes with only empty subtrees between them are also in sight. For instance, the nodes with keys and on the bottom level in Figure 1 are in sight of each other.
Lemma 3.
Let be a WST and a key stored in a node on level in . Then on each level , there is a pair of nodes with such that and .
Proof.
Let be the number of nodes on level . As observed above, all keys on each level of are sorted in ascending order from left to right. Let be the nodes on level from left to right, hence .
If , then , and the pair satisfies all the above conditions.
Otherwise, compare with the keys on level . There are three possible cases:
-
(1)
: In this case, cannot be contained in a subtree further right than rooted on the same level, due to the WST invariant. Hence, , and the pair satisfies the above conditions.
-
(2)
: This case is symmetric to (1), and satisfies the conditions.
-
(3)
: : In this case, can neither be located in a tree further left than nor in a tree further right than . Hence, , and, since , the pair satisfies the conditions.
Lemma 3 states that on each level of a WST, in order to continue the search for a given key , we have to visit at most two different subtrees rooted (in sight of each other) on that level. The question remains whether and how we can identify these subtrees efficiently, i.e. in time per level.
4.2 Walk as a pair
We now outline how lookup of a key can be implemented efficiently on a WST . Instead of using a single pointer for searching, we keep a pair of node pointers that are updated together during each step down the tree, such that , and . Algorithm 2 gives an iterative approach, while Algorithm 3 lists a recursive variant of the same procedure when initially called with the pair .
Note: In line 5, the condition is assumed to return if . The same goes for the condition in line 7 if . The functions and return the leftmost/rightmost existing child node of node , or if no child exists.
Lemma 4.
In , at the beginning of each iteration () of the -loop, either or on the -th level of the tree, and .
Proof.
The invariant obviously holds in the beginning, as , and either or the root is on level .
Within each iteration , we distinguish the following cases:
-
(1)
: In this case, exists and we set and . Hence, we have on level , unless was set to . In that case, line 12 will set and thus, on level .
-
(2)
: This case is completely symmetric to case (1).
-
(3)
In all remaining cases, the algorithm sets to its rightmost child (or , if it has no child) and to its leftmost child (or , if it has no child). Hence, either both and will be on level with , or at least one of them will point to . In the latter case, after lines 12-13 both pointers will point either to the same node on level or to .
Lemma 5.
Assume that key . Then, at the start of each iteration of the -loop in , or .
Proof (by structural induction).
Base case.
The invariant is obviously valid in the beginning when .
Inductive step.
Assume the proposition holds in the beginning of the -th iteration, i.e. or . If either node or node itself contains key , we are done, as the loop will terminate and not enter another iteration.
Otherwise, we have to show that the invariant will also hold in the beginning of the next iteration.
Since and , must be located in one of the four subtrees , , or . Hence, at least one of these subtrees must be non-empty. We show that at least two of the four subtrees can be excluded (also see Fig. 2). First, assume that the two inner subtrees and are non-empty.
-
(a)
If , cannot be contained in a subtree rooted in any node further right than on the same level, due to the weak in-order invariant. Thus, we can exclude both and and continue the search with only and . Hence, we can set and for the next iteration [line 6]. If was empty, we set [line 12].
-
(b)
Symmetrically, if , cannot be contained in any subtree to the left of on the same level. Thus, we can exclude and and continue with only and . We therefore set and for the next iteration [lines 7-8]. If is empty, we set [line 13].
-
(c)
If , cannot be contained in any subtree left of or right of , due to the weak in-order invariant. Thus, we need only consider and for further search. Hence, we set and for the next iteration [lines 10-11].
It remains to consider the cases where or . If both are empty, must be in or , and setting and [lines 10-11] will correctly keep the invariant. If either or is also empty, both and will be set to the only non-empty node [lines 12-13].
If is empty, either case (b) applies (and we are done) or and hence . Lines 9-11 set and , i.e. and point to the only two subtrees where can be located. The last remaining case where is empty can be handled symmetrically.
We can now state our central claim regarding efficient search in WST.
Theorem 6.
Let be a weak binary search tree of height , and let be a key. Then will return the node containing if , or return if , both in time .
Proof.
The algorithm terminates after time steps: Each iteration of the -loop takes at most constant time and, according to Lemma 4, both pointers and descend one level down the tree in each iteration. Hence, the loop terminates after at most iterations.
The correctness of the algorithm for follows directly from Lemma 5. If , both pointers and will be set to after reaching the leaf level [lines 10-11], ending the loop and terminating the algorithm in line 14.
5 Update operations on WST
Using the same principle as for lookup, insertions into or deletions from a WST can also be carried out in time . However, as we shall see, keeping WST in balance is not as straightforward as it is in BST.
5.1 Insert
When inserting a new key in a WST, a suitable insert position can be located via a variant of the lookup operation returning the last visited pair of nodes on the search path if . Note that due to the relaxed in-order invariant, there may be more than one possible insert position for . For instance, when arriving at a leaf node , the new node containing can be inserted as either left or right child of without violating the WST invariant.
A recursive Insert procedure is listed in Algorithm 4. In addition to key , it takes as its input a pair of nodes (either , or one of them ) and descends down the tree recursively using the pair-walk technique. As and move down one level of the tree in each recursive call and attaching the new node is a constant-time operation, the overall time for an insertion is obviously in .
5.2 Delete
Deletion of a key from a WST is particularly easy. First, we locate the node containing with a search that also keeps track of the parent(s) of the last visited pair of nodes. If is a leaf, we can remove it from its parent and are done.
If is an internal node, we replace by the key stored in any leaf node of (and remove that leaf). This will not violate the WST invariant, as the swapped key is only moving upward on its search path.
Clearly, this way of deletion of a key can be carried out in time , as it requires at most one pass down the tree, swap of a key, and removal of one leaf node. A listing of the corresponding algorithm is left as an exercise to the reader.
6 Keeping WST in balance
In order to keep tree search within time bounds, the tree needs to be balanced, i.e. its height must be bounded logarithmically. Brodal [2] gives a thorough overview of balancing methods for BST and also proposes two new algorithms. They rely – as most of the well-known balancing schemes, such as AVL [1] or red-black trees [7] do – on rotations for re-shaping the tree after an update operation. The beauty of rotations is that they are local, constant-time operations and always maintain the in-order invariant.
6.1 The trouble with rotations
Quite surprisingly, a simple rotation can destroy the (weaker) WST invariant. Nodes changing their parent-child relationship in the tree and becoming siblings during a rotation may be out of order with their sibling. An example is shown in Figures 4 and 5.
The reason is that while the in-order invariant is a relationship directly between parent and child keys, the WST invariant is only concerned with neighboring subtrees and oblivious of the key in the common parent node of those subtrees.
Even worse, the possible violation of the WST invariant is not purely local and can affect more than just the two sibling nodes. In Figure 5, subtree and even subtree may contain keys larger than , which can destroy the WST on a larger scale. Hence, simply swapping the two sibling keys and is not sufficient for restoring the WST invariant in the given example.
Fixing the WST after such a rotation therefore involves a larger number of nodes and requires additional passes down the tree. In order to remain in total time for an update operation, a single rotation must remain in time (including subsequent fixes of the invariant) and the number of rotations per update must be bounded by a constant.
We briefly sketch the procedure for fixing the WST invariant after rotations, using the example of the right-rotation from Figure 5:
-
1.
Arrange the keys of the nodes involved in the right-rotation such that the maximum key is stored in the right sibling node .
-
2.
Find the maximum key in subtree (for subtree designations, cf. Figure 5).
-
3.
If , remove from and replace it by any key from either subtree or (all of which are guaranteed to be greater then ). Then insert key in (it will be inserted either in subtree or ).
This restores the WST invariant, but may in turn unbalance the subtree where was inserted. In fact, in the worst case a whole cascade of fixes might be caused until the WST is balanced. The number of steps in the cascade is bounded by the height of , which, in the balanced case, is . Since each restore step also takes time , a complete rebalancing operation may take up to time.
This makes rebalancing more expensive than in BST, and it is an open question whether it is possible in WST to keep updates in worst-case time when using rotations.
6.2 Rebalancing without rotations
As an alternative to rotations, rebalancing can be achieved by restructuring the unbalanced subtree in a different way. A well-known example are scapegoat trees [6], which have the additional charm that they require no balancing information at all in nodes, but only a global integer to maintain information about the tree size. Scapegoat trees are (loosely) weight-balanced, and rebalancing after an update is delayed until a certain threshold of unbalancedness has been reached. In this case the complete unbalanced subtree is rebuilt from scratch into a perfectly balanced tree. This requires sorting all keys in , which breaks the logarithmic worst-case time bound of a single update, but due to delayed rebalancing, the complexity of updates remains in amortized time for standard BST. Also note that rebuilding requires some extra memory (cf. [6] for details).
The above logarithmic time bound is possible since a sorted list of all keys of a subtree in a BST can easily be produced in linear time, as it merely requires an in-order traversal of . In WST, however, keys are not arranged in-order and hence sorting the keys of a subtree is not straightforward. We outline a procedure to turn the keys of a WST subtree into a sorted list. We then show that this can be carried out in average time, as long as and are each balanced. (This is the case if is the first unbalanced node above the position of the update causing the unbalance.)
Algorithm 5 recursively creates sorted key lists from both subtrees of , joins them (i.e. appends one to the other) and then inserts at its appropriate position, such that the resulting list is sorted again. Both and can be achieved in average logarithmic time using skip lists [10].
Lemma 7.
Let be the lowest unbalanced subtree in a scapegoat WST after an update that triggers rebalancing. Algorithm turns into a list of nodes sorted by key in time .
Proof.
The correctness of the algorithm is obvious. We need to show the time bound.
We first consider a balanced (sub)tree of size . Here, each subtree of the root is roughly of size . Joining the subtree lists, as well as insertion of , can be done in time . Hence, the overall average time complexity is given by the recurrence relation .
This resolves to , which is in , as the sum on the right is .
Now consider the unbalanced tree . Let . Then and for some , and the time of the algorithm . Since both and are balanced, .
This leads to the following claim regarding updates on WST.
Theorem 8.
Insertions and deletions on a WST of size can be achieved in expected amortized time.
Proof.
As outlined in section 5, insertions and deletions take time . Using scapegoat trees, binary trees can be rebalanced in amortized time after each update, provided that the tree can be transformed into a fully balanced tree in time . According to Lemma 7, this is possible for WST in the average case.
Note that in Theorem 8 we use the term expected amortized time, as the complexity analysis combines the amortized analysis of scapegoat trees (update times are averaged over a series of update operations) and average case analysis (expected time for an operation, averaged over the possible shapes of skip lists and WST).
7 Conclusion
This paper introduced Weak Binary Search Trees (WST) as a data structure for common dictionary operations. We have shown that despite their weaker invariant, WST search matches the asymptotic bounds of standard BST. This is made possible by the dual-probing approach during search with a pair of pointers being updated simultaneously, limiting the number of inspected nodes on each tree level to .
While insert and delete operations themselves can also be carried out in time , rebalancing the WST after an update is troublesome: rotations may destroy the WST invariant, and fixing it may take time per update operation. Balancing schemes that avoid rotations can help. We outlined how scapegoat trees in combination with skip lists enable updates on WST including rebalancing in expected amortized time. It is an open question whether WST can be updated in worst-case time per insert or delete operation.
Another deficiency of WST is that they cannot easily produce a sorted list of keys with a simple depth-first traversal, like BST. We have shown that with the help of skip lists, the keys of a WST can be transformed to a sorted list in time on average.
While our results may be mainly of theoretical interest and for instructive purposes, WST can also be useful in practical applications, where simple search trees are often augmented with other information. This may impose additional conditions on node relations, which can be hard to satisfy together with the in-order invariant. The weaker WST invariant could be helpful to maintain such augmented structures. In our own current work, we are exploring a WST variant supporting efficient min-heap and max-heap operations in addition to dictionary operations, as well as the combination of two weak data structures – semi-heaps and WST – into a lightweight priority search queue. It will also be interesting to further investigate the problem of rebalancing WST after update operations.
References
- [1] Georgy Maximovich Adelson-Velsky and Evgenii Mikhailovich Landis. An algorithm for the organization of information. Soviet Physics Doklady, 7(5):415–419, 1962.
- [2] Gerth Stølting Brodal. Bottom-up rebalancing binary search trees by flipping a coin. In Andrei Z. Broder and Tami Tamir, editors, 12th International Conference on Fun with Algorithms, FUN 2024, Island of La Maddalena, Sardinia, Italy, June 4-8, 2024, volume 291 of LIPIcs, pages 6:1–6:15. Dagstuhl Publishing, Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2024. doi:10.4230/LIPIcs.FUN.2024.6.
- [3] Minati De, Anil Maheshwari, Subhas C. Nandy, and Michiel H. M. Smid. An in-place priority search tree. In Proceedings of the 23rd Annual Canadian Conference on Computational Geometry, Toronto, Ontario, Canada, August 10-12, 2011, pages 331–336, Toronto, Canada, 2011. URL: http://www.cccg.ca/proceedings/2011/papers/paper41.pdf.
- [4] Minati De, Anil Maheshwari, Subhas C. Nandy, and Michiel H. M. Smid. An In-Place Min-Max Priority Search Tree. Computational Geometry, 46(3):310–327, 2013. doi:10.1016/j.comgeo.2012.09.007.
- [5] Ronald D Dutton. Weak-heap sort. BIT Numerical Mathematics, 33(3):372–381, 1993. doi:10.1007/BF01990520.
- [6] Igal Galperin and Ronald L Rivest. Scapegoat trees. In Proceedings of the fourth annual ACM-SIAM Symposium on Discrete algorithms, pages 165–174, 1993. URL: http://dl.acm.org/citation.cfm?id=313559.313676.
- [7] Leonidas J. Guibas and Robert Sedgewick. A dichromatic framework for balanced trees. In 19th Annual Symposium on Foundations of Computer Science, Ann Arbor, Michigan, USA, 16-18 October 1978, pages 8–21. IEEE, IEEE Computer Society, 1978. doi:10.1109/SFCS.1978.3.
- [8] Ralf Hinze. A simple implementation technique for priority search queues. In Proceedings of the sixth ACM SIGPLAN international conference on Functional programming, pages 110–121, 2001. doi:10.1145/507635.507650.
- [9] Donald Ervin Knuth. The art of computer programming, , Volume III, 2nd Edition. Addison-Wesley, 1998. URL: https://www.worldcat.org/oclc/312994415.
- [10] William Pugh. Skip lists: a probabilistic alternative to balanced trees. Communications of the ACM, 33(6):668–676, 1990. doi:10.1145/78973.78977.
