A Selectable Sloppy Heap

We study the selection problem, namely that of computing the $i$th order statistic of $n$ given elements. Here we offer a data structure called \emph{selectable sloppy heap} handling a dynamic version in which upon request: (i)~a new element is inserted or (ii)~an element of a prescribed quantile group is deleted from the data structure. Each operation is executed in (ideal!) constant time---and is thus independent of $n$ (the number of elements stored in the data structure)---provided that the number of quantile groups is fixed. This is the first result of this kind accommodating both insertion and deletion in constant time. As such, our data structure outperforms the soft heap data structure of Chazelle (which only offers constant amortized complexity for a fixed error rate $0<\varepsilon \leq 1/2$) in applications such as dynamic percentile maintenance. The design demonstrates how slowing down a certain computation can speed up the data structure.


Introduction
The following problem has been devised by Fredman about 25 years ago, for inclusion in homework assignments for an algorithms course. This paper both generalizes and strengthens that result.
A "very sloppy heap" (abbreviated vsh) is a data structure for performing the following operations on a set S: (i) insert and (ii) delete-small. The latter operation deletes (and returns) an element x which is among the ⌈n/2⌉ smallest elements in the set, where n is the current size of the set. Explain how to implement a vsh in constant amortized time per operation.
Together with sorting, selection is one of the most widely used procedure in computer algorithms. Given a sequence A of n numbers and an integer (selection) parameter 1 ≤ i ≤ n, the selection problem asks to find the ith smallest element in A. Sorting trivially solves the selection problem; however, a higher level of sophistication is required by a linear time algorithm. A now classic approach for selection [6,18,25,36,39] from the 1970s is to use an element in A as a pivot to partition A into two smaller subsequences and recurse on one of them with a (possibly different) selection parameter i.
The time complexity of this kind of algorithms is sensitive to the pivots used. If a good pivot is used, many elements in A can be discarded, while if a bad pivot is used, the size of the problem may be only reduced by a constant in the worst case, leading to a quadratic worst-case running time. But carefully choosing a good pivot can be time consuming. Choosing the pivots randomly (and thus without much effort) yields a well-known randomized selection algorithm with expected linear running time; see e.g., [11,Ch. 9.2], [31,Ch. 13.5], or [34,Ch. 3.4]; however its worst case running time is quadratic in n.
The first deterministic linear time selection algorithm Select is due to Blum et al. [6]; it is recursive in nature. By using the median of medians of small disjoint groups of the input array (of constant size at least 5) good pivots that reduce the size of the problem by a constant fraction and thereby lead to O(n) time overall, can be chosen at low cost in each recursive invocation. More recently, suitable variants of Select with groups of 3 and 4 also running in O(n) time have been also put forward [10,40]. The selection problem, and computing the median in particular are in close relation with the problem of finding the quantiles of a set, that we describe next.
Quantiles. The kth quantiles of an n-element set are the k − 1 order statistics that divide the sorted set in k equal-sized groups (to within 1); see, e.g., [11, p. 223]. It is known that the kth quantiles of a set can be computed by a recursive algorithm running in O(n log k) time. Such an algorithm can be modified, if needed, so that the k groups can be also output, say, each as a linked list, within the same overall time. For 2 ≤ i ≤ k − 1, the ith group of elements (bounded by the (i−1)th and the ith quantile) is referred to as the ith quantile group; the first quantile group consists of the elements less or equal to the first quantile, and the kth quantile group consists of the elements greater or equal to the (k − 1)th quantile.
Our main result is the following; for the optimality of the dependence in k, see the first remark in Section 4. Theorem 1. For any fixed integer k, a data structure for dynamic sets exists accommodating each of the following operations in constant time (that depends on k): (i) Insert a new element and (ii) Delete (and return) an element of the ith quantile group of the current set, where 1 ≤ i ≤ k. The time per operation is O(log k), which is optimal in a comparison-based model even in an amortized setting.
Background and related problems. Since the selection problem is of primary importance, the interest in selection algorithms has remained high ever since; see for instance [2,4,5,12,14,15,16,18,20,21,22,23,27,29,35,37,39]. In particular, determining the comparison complexity for computing various order statistics including the median has lead to many exciting questions, some of which are still unanswered today; in this respect, Yao's hypothesis on selection [38,Ch. 4] remains an inspiring endeavor [15,35,36]. A comprehensive review of early developments in selection is provided by Knuth [32]. Computational results on the exact comparison complexity of finding the ith smallest out of n for small i, n, have been obtained in [21,24]. We also refer the reader to the dedicated book chapters on selection in [1,3,11,13,31] and the more recent articles [10,26,30].
The selection problem is also of interest in an online or dynamic setting, where elements are inserted or deleted. A balanced binary search tree on n distinct elements can be augmented with a size attribute for each node, thereby allowing the retrieval of an element of a given rank in O(log n) time [11,Ch. 14]. We say that the ith smallest element has rank i, where i = 1, . . . , n, with ties broken arbitrarily. Further, determining the rank of an element in the data structure can also be done in O(log n) time. Consequently, a dynamic order statistic operation (inserting a new element or deleting an element of a given rank) can be accomplished within the same time bound.
Priority queues (heaps in particular) are ubiquitous data structures; a typical operation set might include Insert, Delete-Min, Decrease-Key (and perhaps also Find-Min, Increase-Key, or other operations). See for instance [7] and the references therein for some new variants and recent developments.
A variant of a priority queue that allows dynamic maintenance of percentiles is the soft heap data structure due to Chazelle [8]; in addition to Create and Meld, the data structure accommodates Insert, Delete and Findmin (Delete x removes item x). Consider a sequence of m ≥ n operations after its creation, that includes n Insert operations. For any 0 < ε ≤ 1/2, a soft heap with error rate ε supports each operation in constant amortized time, except for Insert which takes O(log 1/ε) amortized time. The data structure ensures that at most εn of its items are corrupted (their keys have been artificially raised). Findmin returns the minimum current key (which might be corrupted). In contrast, our data structure uses O(log 1/ε) time per operation, where ε ∼ 1/k, and thereby outperforms the soft heap with respect to the worst-case time per update (insert or delete) operation.
Definition. Let k be a fixed positive integer. A "selectable sloppy heap" (abbreviated ssh) is a data structure for performing the following operations on a set S with n elements: (a) Insert x: a new element x is inserted.
(b) Delete i: this deletes (and returns) some element x which belongs to the ith quantile group of the current set, where 1 ≤ i ≤ k; if n < k, the deleted element is not subject to any requirement.
Outline of the paper. To explain the main challenges and introduce the main ideas, we first sketch several preliminary implementations of the data structure, meeting suboptimal (in k) benchmarks: (i) O(k log k) amortized time per operation for the first variant in Section 2; (ii) O(k log k) worst-case time per operation for the second variant in Section 2; (iii) O(log k) amortized time per operation for the third variant in Section 2. We then further refine these methods in Section 3 to obtain an optimal implementation of the data structure running in O(log k) worst-case time per operation. In particular, for constant k, the second variant in Section 2 and the (main) variant in Section 3 run in O(1) worst-case time per operation. We conclude in Section 4 with applications and technical remarks.
Comments and notations. Duplicate elements are easily handled by the design. Each operation request is associated with a discrete time step, i.e., the jth operation occurs during the jth time step, where j = 1, 2, . . . Without affecting the results, the floor and ceiling functions are omitted in the descriptions of the algorithms and their analyses. Let A be a set; we write x ≤ A if x ≤ a for every a ∈ A. The size of a bucket b, i.e., the number of elements in b, is denoted by s(b). If buckets b ′ and b ′′ merge into a new bucket b, written as

Some ideas and preliminary solutions
A first variant with O(k log k) amortized time per operation. Let n denote the current number of elements in the data structure, with the elements being stored in a linear list (or an array). By default (if n is large enough) the algorithm proceeds in phases.
If n < 3k, and no phase is under way, proceed by brute force: for Insert, add the new element to the list; for Delete i, compute the elements in the ith quantile group and delete (return) one of them arbitrarily. Since k is constant, each operation takes O(3k), i.e., runs in constant time.
If n ≥ 3k, and no phase is under way, start a new phase: reorganize the data structure by computing the 3kth quantiles of the set and the corresponding groups; store each group in a list (bucket) of size n/(3k). The next n/(3k) operations make up the current phase. Process each of these n/(3k) operations by using exclusively elements stored in these 3k buckets. For Insert, add the new element to an initially empty overflow bucket (an empty overflow bucket is created at each reorganization). For Delete i, remove any element from the bucket (i − 1) n k + n 3k , i.e., from the middle third of the ith quantile group (out of the total k).
The reorganization takes O(n log k) time and is executed about every n/(3k) steps, where each operation counts as one step. The resulting amortized cost per operation is namely O(1) for constant k. The above idea is next refined so as to obtain this as a worst-case time bound per operation.
A second variant with O(k log k) worst-case time per operation. It suffices to consider the case of large n, namely n ≥ 3k. The algorithm proceeds in phases: each phase starts with a reorganization, namely computing the (3k)th quantiles and the corresponding quantile groups; see [11,Ch.15]. The time taken is O(n log (3k)) = O(n log k). There are n/(3k) Insert and Delete operations, i.e., n/(3k) steps following each reorganization until the results of the next reorganization become available: assume that the data structure holds n items when the current reorganization starts (n is redefined at the start of each reorganization) and there are old buckets to use until the reorganization is finalized. That is, after that many steps new buckets (however, with an old content) become available. Use these buckets for the next n/(3k) operations, and so on.
To transform the constant amortized time guarantee into a constant worst-case guarantee for each operation, spread the execution of reorganization over the next n/(3k) operations, i.e., over the entire phase. The resulting time per operation is bounded from above by Since Delete is serviced from the existent buckets and Insert is serviced using the overflow bucket, each operation involves inserting or deleting one element from a list; thus for constant k, each operation takes O(1) overall time to process.
New buckets become available about every other n/(3k) operations; this is a rather imprecise estimate because the current number of elements, n, changes. Since a reorganization is spread out over multiple steps, the result becomes available with some delay, and moreover, its content is (partially) obsolete. To verify that the data structure operates as intended, one needs to check that the rank of a deleted element belongs to the required interval (quantile group); we omit the calculation details. The key observation is that any one operation can affect the rank of any element by at most 1: to be precise, only Insert or Delete of a smaller element can increase the rank of an element by 1 or decrease the rank of an element by 1, respectively.
A third variant with O(log k) amortized time per operation. We briefly describe an implementation achieving O(log k) amortized time per operation that is tailored on the idea of a B-tree; this variant is due to Fredman [19]. Use a balanced binary search tree with Θ(log k) levels storing O(k) splitting keys at the leafs. Each leaf comprises a bucket of Θ(n/k) items, with order maintained between buckets, but not within buckets. When an insertion causes a bucket to become too large, it gets split into two buckets by performing a median selection operation. Small buckets (due to deletions) get merged. A bucket of size m, once split, won't get split sooner than another Ω(m) operations.
When the number of elements doubles (or halves), a tree reorganization is triggered that partitions the present items into 6k uniform sized buckets, so that the new common bucket size m is n/(6k) items. These event-triggered reorganizations ensure that buckets do not become too small unless they are target of deletions; similarly, buckets do not become too large unless they are target of insertions. Since the reorganization cost is O(n log k), and Ω(n) operation requests take place between successive reorganizations, this scheme yields O(log k) amortized time per operation, namely O(1) for constant k.

A variant with optimal O(log k) worst-case time per operation
A brief examination of the approach in the 3rd variant reveals two bottlenecks in achieving O(log k) worst-case time per operation: the median computation that comes with splitting large buckets and the tree reorganization that occurs when n doubles (or halves). We briefly indicate below how ideas from the 2nd and 3rd early variants are refined to obtain O(log k) worst-case time per operation; in particular, O(1) time for constant k. It is shown in the process how execution in parallel of several sequential procedures can lead to a speed up of the data structure.
A balanced BST for Θ(k) keys is used, subdividing the data into O(k) buckets. A size attribute is associated with each node reflecting the number of elements stored in the subtree rooted at the respective node. Modifications in the data structure at each operation are reflected in appropriate updates of the size attributes at the O(log k) nodes of the O(1) search paths involved, in O(log k) time overhead per operation.
If n is the current number of elements, each bucket holds at most n/(3k) elements, and so each of the k quantile groups contains at least one of the buckets entirely. By choosing one such bucket at the bottom of the search path in the BST for executing a Delete operation from the ith quantile group guarantees its correctness.
The n elements are kept in Θ(k) buckets of maximum size O(n/k) that form the Θ(k) leaves of a balanced binary search tree A. As in the third variant (in Section 2), each leaf holds a bucket, with order maintained between buckets, but not within buckets. Buckets that become too large are split in order to enforce a suitable upper limit on the bucket size. Median finding procedures along with other preparatory and follow-up procedures accompanying bucket splits are scheduled as background computation, as in the second variant (in Section 2).
Our data structure merges small buckets in order to keep the number of buckets under control and renounces the periodic tree reorganizations by introducing new elements of design: a round robin process and a priority queue jointly control the maximum bucket size and the number of buckets in the BST. These mechanisms are introduced to prevent buckets becoming too small or too large as an effect of changes in the total number of elements, n, and not necessarily as an effect of operations directed to them.
Outline and features. Let N := 12k. For illustrating the main ideas, assume now that n ≥ N . The buckets are linked in a doubly-linked linear list B, in key order; adding two links between the last and the first bucket yields a circular list C, referred to as the round robin list. We note that B and C are two views of the same data structure.
Each operation request translates to locating a suitable bucket for implementing the request. The circular list is traversed in a round robin fashion, so that the current round robin bucket in the list is also examined during the current operation request. The round robin process ensures that (i) the buckets do no exceed their maximum capacity, and (ii) certain "long-term" preparatory bucket-splitting procedures are run in the background over a succession of non-consecutive discrete time steps allocated to the same bucket.
Each bucket split entails a merge-test for the pair of adjacent buckets with the minimum sum of sizes. The process of merging adjacent buckets in B is controlled by a priority queue in the form a binary min-heap H. If |B| = t, i.e., there are t buckets, H holds the t − 1 sums of sizes s(b) + s(b + ), for buckets b ∈ B; here b + denotes the bucket that follows b in B. A merge is made provided the minimum value at the top of H is below some threshold; and A, B and H are updated. Merging adjacent buckets ensures that the total number of buckets remains under control, regardless of which buckets are accessed by operation requests.
Elements of the design. We highlight two: (i) use of the priority queue H to keep the number of buckets under control, and (ii) running the procedures involved at different rates as needed to ensure that certain task deadlines and precedence constraints among them are met. The data structure maintains the following two invariants: I1 Each bucket contains between 1 and n/(3k) elements; there is no limit from below imposed on the bucket size.

I2
The number of buckets is between 3k and N = 12k, as implied by the maximum bucket size, and a later argument based on the rules of operation (on merging adjacent buckets); see Action 2 and Lemma 1.
Recall that all Θ(k) buckets are linked in a circular round robin list: in key order, and with the last bucket linked to the first one. A pointer to the current round robin bucket (initialized arbitrarily, say, to the first bucket) is maintained. Each operation request advances this position in the list by one slot. Observe that every bucket becomes the round robin bucket about every Θ(k) discrete time steps. Further, each operation request leads via the search path in A to one of the buckets, referred to as the operation bucket. Executing one operation is done by a sequence of actions performed in the operation bucket and the round robin bucket; these are referred to as the current buckets. All these actions are therefore associated with the same discrete time step. Every bucket update (this includes creation or deletion of buckets) entails a corresponding update of the binary heap H in the (at most) two heap elements s(b) + s(b + ) that depend on it.
A bucket is declared large if its current size exceeds 9/10 of the maximum allowed, i.e., if the current size exceeds 9n/(30k). All other buckets are declared regular. Each operation may cause an update in the status of the round robin bucket and the operation bucket (among large and regular). Action 1. Execute the requested operation: either add a new element to the respective bucket, or delete an arbitrary element from it. If the operation bucket becomes empty as a result of the current Delete operation, it is deleted, and the BST is correspondingly updated in O(log k) time. Status updates in the current two buckets are made, if needed. If a median finding procedure or a follow up procedure is under way in the current operation bucket or the current round robin bucket (see details below), the next segment consisting of 500 (or less) elementary operations of this procedure is executed. It is worth noting that a bucket for which a partitioning procedure is under way, as described below, cannot be part of a pair of buckets to merge (i.e., passing the merge-test).
Action 3 (finalizing a split). Similar to the merge operations in Action 2, finalizing the split can be completed in O(log k) time: it essentially involves updating A, B and H. It will be shown subsequently that the size of any new bucket resulting from a split is in the range [4n/(30k), 6n/(30k)].
Besides Actions 1 − 3, there are actions associated with procedures running in the background, whose execution is spread out over a succession of non-consecutive discrete time steps allocated to the same bucket. The procedures are in preparation of splitting large buckets.
Splitting a large bucket. For simplicity of exposition, we assume that n = Ω(k), for a sufficiently large constant factor. If the current bucket b is large, i.e., s(b) ≥ 9n/(30k), and no procedure is active in the current bucket, let n 0 := n (the number of elements existent when the procedure is initiated); and place 8.8n 0 /(30k) elements into (a main part) P 1 and the remaining s(b) − |P 1 | elements into (a secondary part) P 2 . Observe that 0.2n 0 /(30k) ≤ |P 2 | ≤ 0.4n 0 /(30k). Any insertions and deletions from the current bucket until the split is finalized are performed using P 2 . A balanced partition of the current bucket will be obtained in at most n 0 /10 time steps.
Consider the following n 0 /10 operation requests. By Lemma 1 below, the number of buckets is at most 12k at any time, and so at least (n 0 /10)/(12k) = n 0 /(120k) time steps are allocated to b in the round robin process by the n 0 /10 time mark. Let t 1 , where n 0 /(120k) ≤ t 1 < n 0 /10, mark the first occurrence when a total of n 0 /(120k) discrete time steps have been allocated to b (as operation steps or round robin steps). As shown next, this number of steps suffices for finalizing the balanced partition and the split of b. The process calls two procedures, labeled (A) and (B): (A) Start a median finding procedure, i.e., for finding the two quantile groups Q 1 , Q 2 of P 1 : an element m ∈ Q 1 ∪ Q 2 = P 1 is found so that Q 1 ≤ m ≤ Q 2 and ||Q 1 | − |Q 2 || ≤ 1. At the point when this procedure is launched, the computational steps are scheduled so that every time the bucket gets accessed (either as the operation bucket or as the round robin bucket), 500 computational steps for selecting the median element of P 1 take place. Assume for concreteness that median finding on an input set S takes at most 10|S| elementary operations; when applied to P 1 , we have |P 1 | ≤ 8.8n 0 /(30k), and thus 88n 0 /(30k) elementary operations suffice. At the rate of 500 per discrete time step, it follows that 88n 0 /(15000k) ≤ n 0 /(160k) time steps suffice for finding the median of P 1 .
(B) After the median has been determined, a follow up procedure is initiated in the same bucket. It aims at reducing and finally eliminating the leftover of P 2 , so that in another n 0 /(480k) discrete steps, a balanced partition of the current bucket is obtained. The follow up procedure starts with the two quantile groups of the same size, 4.4n 0 /(30k), as created by the median finding procedure, by comparing each element of P 2 against m and properly placing it in one of the two groups. This procedure runs at the rate of 10 items per discrete time step accessing the current bucket (either as the operation bucket or as the round robin bucket), until finally the partitioning process is completed with all elements in the current bucket properly placed against the pivot m. Note that |P 2 | ≤ 0.4n 0 /(30k) + n 0 /(480) ≤ 0.5n 0 /(30k) at any time; at the rate of 10 items per discrete time step, it follows that 0.5n 0 /(300k) ≤ n 0 /(480k) time steps suffice for completing the follow up procedure.
The two procedures terminate within a total of at most n 0 /(160k) + n 0 /(480k) = n 0 /(120k) discrete time steps, as required. The parameters are chosen so that the split takes place before the large bucket b becomes illegal.
Recall that 0.9n 0 ≤ n ≤ 1.1n 0 ; thus, in terms of the current number of elements, n, the split of a large 1 bucket b produces two smaller buckets Overlapping partitioning phases in the same bucket are precluded by the fact that no fewer than 3n/(30k) data structure operations accessing a given fresh bucket can trigger the next launching of a partitioning phase for that bucket.
Remark. Let b be a new bucket produced in the current operation. If b is generated by a split operation, then 4n 30k ≤ s(b) ≤ 6n 30k by (1). If b is generated by a merge operation, then s(b) ≤ 5n 30k by the merge-test.
Analysis of merging buckets and maintaining the two invariants. To prove that the two invariants I1 and I2 are maintained, we need the following key fact. Lemma 1. The number of buckets is at most N = 12k at any time.
Proof. Let t denote the number of buckets after the current operation is executed, and j = 1, 2, . . . denote the discrete time steps. Let B 1 , . . . , B t be the buckets after the current step in key order. Write a i = s(B i ), for i = 1, . . . , t. We proceed by induction on j and show that, if the number of buckets in A (and B) is at most N after each of the preceding N time steps, it remains at most N after the current time step. Observe that the number of buckets can only increase by one after a bucket split, and there can be at most two splits associated with a discrete time step. The induction basis is j ≤ N , and then indeed, we have t ≤ j ≤ N , as required.
For the induction step, assume that the number of buckets is at most N after the previous operation. If no bucket splits occur during the execution of the current operation, the number of buckets remains unchanged, and is thus still at most N after the current operation. If bucket splits occur, it suffices to show that the number of buckets is at most N after each split. Consider a split operation, and let σ := s(b) + s(b + ) be the minimum value at the top of the heap H after the split. There are two cases: Case 1. σ ≤ 5n/(30k), and thus the merge is executed. Consequently, the number of buckets after the split is still at most N , as required.
Case 2. σ > 5n/(30k), and thus no merge is executed. Since H is a min-heap, we have Adding these t − 1 inequalities yields or t ≤ 12k = N , as claimed, and concluding the induction step.

Applications and technical remarks
1. An argument due to Fredman [19] shows that executing a sequence of n operations (from among Insert and Delete i, where 1 ≤ i ≤ k) requires Ω(n log k) time in the worst case, regardless of the implementation of the data structure. The argument relies on the information theory lower bound [32,Ch. 5.3.1]. (For completeness, it is included in the Appendix.) 2. In addition to the two operations provided Insert and Delete i, the following operation can be also accommodated at no increase in cost: Read i: this returns some element x which belongs to the ith quantile group of the current set, where 1 ≤ i ≤ k; the element remains part of the data structure.
3. The new data structure finds applications in settings with large dynamic sets where insertions and deletions need to be handled fast, and there is no need to be very precise with the ranks of the elements handled. One such application is approximate sorting. An array of n elements is said to be L-sorted if for every i ∈ [n], we have |rank(a i ) − i| ≤ L; see also [17,33]. As shown by the lower bound argument, the selectable sloppy heap can be used to L-sort n elements in O(n log (n/L)) time.
4. As mentioned in the introduction, the selection problem, and computing the median in particular, are in close relation with the problem of finding the quantiles of a set. A typical use of the median relies on its property of being both larger or equal and smaller or equal than a constant fraction of the n elements. Following Yao [38], an element (think of a player, in the context of tournaments) is said to be (i, j)-mediocre if it is neither among the top i nor among the bottom j of a totally ordered set S. As such, an element from the middle third quantile group of an n-element set is (⌊n/3⌋, ⌊n/3⌋)-mediocre; or simply mediocre, for short. Repeatedly returning a mediocre element in a dynamic setting (with an initially empty set) can thus be accomplished via the new data structure, by setting k = 3 and then repeatedly executing Delete 2 or Read 2, as needed, at a minimal (constant) query cost. Similarly, putting k = 100 sets up the data structure for dynamic percentile maintenance in O(1) time per operation; to the best of our knowledge, this outperforms previously available data structures with respect to this application; e.g., the soft heap data structure of Chazelle [8] only offers constant amortized time per operation.

5.
Here we continue our earlier discussion in Section 1 on using BSTs in the context of dynamic selection taking into account the new data structure. Traditionally, search trees do not allow duplicate keys; it is however an easy matter to augment each node of such a tree with a multiplicity attribute associated with each distinct key. In particular, the multiplicity attribute is taken into account when computing the size attribute of a node. Now having a balanced search tree augmented as described, insertion, deletion and search all take O(log n) time.
Our construction method can be used for any parameter k, with 2 ≤ k ≤ n. The data structure obtained in this way can be viewed as an approximate search tree. In particular, one can search for a given key and the approximate rank of a search key can be determined. To be precise, the following hold: (1) For any 2 ≤ k ≤ n, an approximate search tree on n items (duplicate keys allowed) can be constructed in O(n log k) time. (2) Search for a given key takes O(n/k+log k) time per operation; its approximate rank, i.e., the quantile group to which it belongs (out of k), can be reported in O(log k) time (regardless of the presence of the key!). It is worth noting that the approximate search tree we just described appears competitive when k is small and the search function is infrequently used. Then insertion and deletion of an unspecified key from a given quantile group (out of k) takes O(log k) time (the deleted element is revealed after the operation); e.g., if k = O(log n), these operations take O(log log n) time. On the other hand, the approximate search tree we just described is no real competitor for the exact solution previously discussed; indeed, no choice of k in our data structure would allow an improvement in the performance of all the basic three operations.
6. An alternative solution (to that outlined in Section 3) achieving O(log k) worst-case time per operation was conceived by Fredman [19] (after the author of the current paper has communicated him the main result). (i) His solution avoids the need to merge small buckets (in order to keep the number of buckets under control) by maintaining two running copies of the data structure and performing periodic tree reorganizations that create uniform-sized buckets. Buckets that become large are split using a mechanism similar to that devised here-in Section 3. While a complete description of this solution is not publicly available, the fact is that the decision of avoid merging small buckets comes at a high price. The main reasons are the need to maintain multiple running copies of the data structure (with two copies under permanent construction, etc), handling subtle consistency issues generally hard to satisfy, and the likely reduced speed caused by the above items. (ii) Another cumbersome approach claimed to be a simplification can be found in his subsequent arXiv posting. As such, neither alternative solution ((i) or (ii) above) matches in elegance and simplicity the one given here. 7. As mentioned earlier, the O(log 1/ε) amortized complexity of the soft heap is optimal, however this does not hold for its worst-case complexity, in regard to its Insert, Delete and Findmin operations. In contrast, the O(log 1/ε) worst-case complexity per operation of the selectable sloppy heap is optimal (where ε ∼ 1/k).
8. Interestingly enough, most applications envisioned by Chazelle [8] for the soft heap (i.e., four items from his list of five) can be dealt with using the selectable sloppy heap; these include dynamic maintenance of percentiles, linear-time selection, and two versions of approximate sorting. One can observe that the complexity analysis for the soft heap, of the error rate in particular, is more complicated than that for the selectable sloppy heap; moreover, special effort is required to ensure that the space needed by the soft heap is linear in the number of items present. In at least one application, approximate sorting, the analysis of doing that with a soft heap is more involved than that for using our structure for this task. Needless to say, the soft heap only allows deletion of small items. As such, the new data structure presented here compares favorably to the soft heap with respect to insertion and deletion. Moreover, the constant amortized guarantee per operation is replaced by the stronger constant worst-case guarantee per operation in our case.
It is worth recalling that the soft heap was designed with a specific application in mind, minimum spanning trees. Given a connected graph G = (V, E), where |V | = n, |E| = m, with weighted edges, Chazelle [9] showed that a minimum spanning tree (MST) can be computed by a deterministic algorithm in O(mα(m, n)) time, where α is the (slowly growing) inverse of the Ackermann function. (A randomized linear-time algorithm was given by Karger et al. [28].) The question of whether the selectable sloppy heap can be used for MST computation is left open.