Fast Breadth-First Search in Still Less Space
Torben Hagerup

TL;DR
This paper presents a space-efficient algorithm for breadth-first search that operates in linear time using significantly less memory than traditional methods, making it suitable for large graphs.
Contribution
It introduces a novel BFS algorithm that uses only about n log2 3 bits of memory, reducing space requirements while maintaining linear time complexity.
Findings
BFS can be performed in O(n+m) time with minimal memory.
The algorithm uses n log2 3 + O((log n)^2) bits of space.
The approach improves space efficiency over existing BFS implementations.
Abstract
It is shown that a breadth-first search in a directed or undirected graph with vertices and edges can be carried out in time with bits of working memory.
Peer Reviews
No public reviews on file for this paper yet. If you reviewed it on a platform where reviews are public (OpenReview, ICLR, NeurIPS, ICML), you can paste yours below so the community can read it here.
Videos
No videos yet. Explain this paper in a talk, walkthrough, or lecture? Add one.
11institutetext: \Tinfuna[5]
11email: [email protected]
Fast Breadth-First Search in Still Less Space
Torben Hagerup
Abstract
It is shown that a breadth-first search in a directed or undirected graph with vertices and edges can be carried out in time with bits of working memory.
Keywords: Graph algorithms, space efficiency, BFS, choice dictionaries.
1 Introduction
1.1 Space-Bounded Computation
The study of the amount of memory necessary to solve specific computational problems has a long tradition. A fundamental early result in the area is the discovery by Savitch [13] that the - connectivity problem (given a graph and two vertices and in , decide whether contains a path from to ) can be solved with bits of memory on -vertex graphs. In order for this and related results to make sense, one must distinguish between the memory used to hold the input and the working memory, which is the only memory accounted for. The working memory is usable without restrictions, but the memory that holds the input is read-only and any output is stored in write-only memory. Informally, these conventions serve to forbid “cheating” by using input or output memory for temporary storage. They are all the more natural when, as in the original setting of Savitch, the input graph is present only in the form of a computational procedure that can test the existence of an edge between two given vertices.
Savitch’s algorithm is admirably frugal as concerns memory, but its (worst-case) running time is superpolynomial. It was later generalized by Barnes, Buss, Ruzzo and Schieber [4], who proved, in particular, that the - connectivity problem can be solved on -vertex graphs in time using bits for arbitrary fixed . In the special case of undirected graphs, a celebrated result of Reingold [12] even achieves polynomial time with just bits. The running times of the algorithms behind the latter results, although polynomial, are “barely so” in the sense that the polynomials are of high degree. A more recent research direction searches for algorithms that still use memory as sparingly as possible but are nonetheless fast, ideally as fast as the best algorithms that are not subject to space restrictions. The quest to reduce space requirements and running time simultaneously is motivated in practical terms by the existence of small mobile or embedded devices with little memory, by memory hierarchies that allow smaller data sets to be processed faster, and by situations in which the input is too big to be stored locally and must be accessed through query procedures running on a remote server. The Turing machine models running time on true computers rather crudely, so the model of computation underlying the newer research is the random-access machine and, more specifically, the word RAM.
1.2 The Breadth-First-Search Problem
This paper continues an ongoing search for the best time and space bounds for carrying out a breadth-first search or BFS in a directed or undirected graph. Formally, we consider the BFS problem to be that of computing a shortest-path spanning forest of an input graph consistent with a given permutation of in top-down order, a somewhat tedious definition of which can be found in [8]. Suffice it here to say that if all vertices of the input graph are reachable from a designated start vertex , the task at hand essentially is to output the vertices in in an order of nondecreasing distance from in . The BFS problem is important in itself, but has also served as a yardstick with which to gauge the strength of new algorithmic and data-structuring ideas in the realm of space-efficient computing.
In the following consider an input graph and take and . The algorithms of Savitch [13] and of Barnes et al. [4] are easily adapted, within the time and space bounds cited above, to compute the actual distance from to ( if is not reachable from ). As a consequence, the BFS problem can be solved on -vertex graphs with bits or in time with bits. Every reasonably fast BFS algorithm known to the author, however, can be characterized by an integer constant , dynamically assigns to each vertex in one of states or colors, and maintains the color of each vertex explicitly or implicitly. Let us call such an algorithm a -color BFS algorithm. E.g., the classic BFS algorithm marks each vertex as visited or unvisited and stores a subset of the visited vertices in a FIFO queue, which makes it a 3-color algorithm: The unvisited vertices are white, the visited vertices in the FIFO queue are gray, and the remaining visited vertices are black. Because the distribution of colors over the vertices can be nearly arbitrary, a -color BFS algorithm with an -vertex input graph must spend at least bits on storing the vertex colors. The classic BFS algorithm uses much more space since the FIFO queue may hold nearly vertices and occupy bits.
Similarly as Dijkstra’s algorithm can be viewed as an abstract algorithm turned into a concrete algorithm by the choice of a particular priority-queue data structure, Elmasry, Hagerup and Kammer [6] described a simple abstract 4-color BFS algorithm that uses time plus calls of operations in an appropriate data structure that stores the vertex colors. This allowed them to derive a first BFS algorithm that works in time with bits. Using the same abstract algorithm with a different data structure, Banerjee, Chakraborty and Raman [2] lowered the space bound to bits. Concurrently, Hagerup and Kammer [9] obtained a space bound of bits, for arbitrary fixed , by stepping to a better so-called choice-dictionary data structure but, more significantly, by developing an abstract 3-color BFS algorithm to work with it. The algorithm uses the three colors white, gray and black and, for an undirected graph in which all vertices are reachable from the start vertex , can be described via the code below. No output is mentioned, but a vertex can be output when it is colored gray.
[TABLE]
Roughly speaking, the white vertices have not yet been encountered by the search, the black vertices are completely done with, and the gray vertices form the layer of currently active vertices at a common distance from . The two inner loops of the algorithm iterate over the gray vertices in order to replace them by their white neighbors, which form the next gray layer. Both iterations are dynamic in the sense that the set of gray vertices is changing while it is being iterated over. The first iteration colors additional vertices gray, and we would prefer for these newly gray vertices not to be enumerated by the iteration. Satisfying this requirement is not easy for a space-efficient algorithm, however, and therefore the iteration instead tests each enumerated vertex for being “old”—exactly then does it equal or have a black neighbor—and ignores the other gray vertices. Similarly, the second iteration colors black only those gray vertices that are no longer needed as neighbors of white vertices—these include all “old” gray vertices. Even so, the choice dictionary must support dynamic iteration suitably. This represents the biggest challenge for a space-efficient implementation of the abstract algorithm.
For a directed graph, the changes are slight: “black neighbor” should be replaced by “black inneighbor”, and each of the two occurrences of “white neighbor” should be replaced by “white outneighbor”. If not all vertices are reachable from , the code above, except for its first line, must be wrapped in a standard way in an outer loop that steps through all vertices in a suitable order and restarts the BFS at every vertex found to still be white when it is chosen as . This leads to no additional complications and will be ignored in the following.
1.3 Recent Work and Our Contribution
Starting with the algorithm of Hagerup and Kammer [9], all new BFS algorithms have space bounds of the form bits for some function with . In a practical setting the leading factor of is likely to matter more than the exact form of , so that the progress since the algorithm of Hagerup and Kammer could be viewed as insignificant. However, at least from a theoretical point of view it is interesting to explore how much space is needed beyond the seemingly unavoidable bits required to store the vertex colors. If a 3-color BFS algorithm uses bits, we will therefore say that it works with extra bits. If its running time is , we may summarize its resource requirements in the pair . Adapting the notion of pareto dominance, we say that an algorithm with the resource pair dominates an algorithm with the resource pair if and or and .
Banerjee, Chakraborty, Raman and Satti [3] indicated a slew of 3-color BFS algorithms with the following resource pairs: , , and for certain slowly growing functions . The first of these algorithms is dominated by that of Barnes et al. [4], which also uses polynomial time but bits altogether, not just extra bits. The third algorithm of [3] is dominated by the algorithm of Hagerup and Kammer [9], whose resource pair is for arbitrary fixed . Instantiating the 3-color abstract algorithm of [9] with a new choice dictionary, Hagerup [8] obtained an algorithm that has the resource pair and dominates the two remaining algorithms of [3]. Another algorithm of [8] is faster but less space-efficient and has the resource pair for arbitrary fixed .
Here we present a new data structure, designed specifically to be used with the abstract 3-color BFS algorithm of [9], that leads to a concrete BFS algorithm working in time using bits of working memory. The new algorithm combines the best time and space bounds of all previous algorithms with running-time bounds of or less, and therefore dominates all of them. It is also simpler than several previous algorithms. We obtain a slightly more general result by introducing a tradeoff parameter : The running time is , and the space bound is bits. If the degrees of the vertices of the input graph form a nondecreasing sequence or if is approximately regular, we achieve a running time of with just bits.
The technical contributions of the present paper include:
- •
A new representation of vertex colors
- •
A new approach to dynamic iteration
- •
A refined analysis of the abstract 3-color BFS algorithm of [9] and of a data structure of Dodis, Pǎtraşcu and Thorup [5] for storing nonbinary arrays
- •
An amortized analysis of the new data structure.
Conversely, we draw on [9] not only for its abstract 3-color BFS algorithm, but also for setting many of the basic concepts straight and for a technical lemma. Another crucial component is the in-place chain technique of Katoh and Goto [11], as developed further in [8, 10]. The fundamental representation of colors drawn from in close to bits so as to support efficient access to individual colors, also alluded to above, is due to Dodis et al. [5].
2 Preliminaries
We do not need to be very specific about the way in which the input graph is presented to the algorithm. With and , we assume that can be determined in time and that . If is undirected, we also assume that for each vertex , it is possible to iterate over the neighbors of in at most constant time plus time proportional to their number. If is directed, the assumption is the same, but now the neighbors of include both the inneighbors and the outneighbors of , and inneighbors should (of course) be distinguishable from outneighbors.
Our model of computation is a word RAM [1, 7] with a word length of bits, where we assume that is large enough to allow all memory words in use to be addressed. As part of ensuring this, we assume that . The word RAM has constant-time operations for addition, subtraction and multiplication modulo , division with truncation ( for ), left shift modulo (, where ), right shift (), and bitwise Boolean operations (and, or and xor (exclusive or)).
3 The Representation of the Vertex Colors
This section develops a data structure for storing a color drawn from the set for each of the vertices in . The data structure enables linear-time execution of the abstract 3-color BFS algorithm of [9] and occupies bits. An inspection of the algorithm reveals that the operations that must be supported by the data structure are reading and updating the colors of given vertices—this by itself is easy—and dynamic iteration over the set of gray vertices. A main constraint for the latter operation is that the iteration must happen in time proportional to the number of gray vertices, i.e., we must be able to find the gray vertices efficiently.
Let us encode the color white as , gray as and black as . In the following we will not distinguish between a color and its corresponding integer or 2-bit string. Take , and . In the interest of simplicity let us assume that is large enough to make . In order to keep track of the colors of the vertices in we divide the sequence of colors into segments of exactly colors each, with at most colors left over. Each segment is represented via a big integer drawn from . Because , big integers can be manipulated in constant time. The big integers are in turn maintained in an instance of the data structure of Lemma 3.1 below, which occupies bits.
Lemma 3.1** ([5], Theorem 1).**
There is a data structure that, given arbitrary positive integers and with , can be initialized in time and subsequently maintains an array of elements drawn from in bits such that individual array elements can be read and updated in constant time.
3.1 Containers and Their Structure and Operations
We view the big integers as objects with a nontrivial internal structure and therefore use the more suggestive term container to denote the big integer in a given position in the sequence of big integers. We shall say that each of the vertices whose colors are stored in a container is located in the container. A container may represent colors in several different ways illustrated in Fig. 1. The most natural representation is as the integer . We call this the regular representation, and a container is regular if it uses the regular representation (Fig. 1(b)). When a vertex is located in a regular container, we can read and update the color of in constant time, provided that we store a table of the powers . E.g., with notation as above, for . The table occupies bits and can be computed in time.
We allow a variant in which a regular container is a master (Fig. 1(a)). The difference is that the most significant bits of the big integer corresponding to are relocated to a different container , said to be the slave corresponding to , and stored there. This frees bits in for other uses (the most significant bit is fixed at 0 to ensure that the value of the big digit does not exceed ). Since , we can store a pointer (possibly null) to a container in bits, so a master has room for three such pointers. One of these designates the slave , while the use of the two other pointers, called iteration pointers, is explained later. Even though it may be necessary to access the data relocated to the slave, a master still allows vertex colors to be read and updated in constant time.
When it is desired to iterate over the gray vertices in a regular container, a copy of the container is first converted to the loose representation, in which the 2-bit strings corresponding to the color values are simply concatenated to form a string of bits. Since , this can be done in time with the algorithm of Lemma 3.2 below, used with , and . The algorithm is a word-parallel version (i.e., essentially independent computations take place simultaneously in different regions of a word) of a simple divide-and-conquer procedure.
Lemma 3.2** **([8],
Lemma 3.3 with and ).
Given integers , and with , and and an integer of the form , where for , the integer can be computed in time.
Conversely, using the lemma instead with and , we can convert from the loose to the regular representation, again in time. Once a container is in the loose representation, we can locate the first (smallest) gray vertex in the container in constant time with the algorithm of part (a) of the following lemma that, again, draws heavily on word-parallel techniques. Here we use the lemma with and .
Lemma 3.3** **([9],
Lemma 3.2**).**
Let and be given integers with and suppose that a sequence with for is given in the form of the -bit binary representation of the integer . Then the following holds:
- (a)
Let and . Then, in time, we can test whether and, if not, compute .
- (b)
If and an additional integer is given, then and can be computed in time.
Subsequently, if we remember the last grey vertex enumerated, we can shift out that vertex and all vertices preceding it before applying the same algorithm. This enables us to iterate over the set of gray vertices in the container in time. The colors of the at most vertices left over from the division into segments are kept permanently in what corresponds to the loose representation. This uses bits, and it will be obvious how to adapt the various operations to take these vertices and their colors into account, for which reason we shall ignore them in the following.
If a container is a slave (Fig. 1(d)), we require the number of gray vertices in the container to be bounded by , and we store its gray vertices separately in a gray list. The gray list takes the form of the integer , stored (somewhat wastefully) in bits, followed by a sorted sequence of integers, each represented in bits, that indicate the positions of the gray vertices within the container. By the assumption , the gray list fits within bits. Because of the availability of the gray list, we can store the remaining vertex colors in a black-and-white vector of just bits by dropping the most significant bit, which normally allows us to distinguish between the colors gray and black, from all 2-bit color values. Since and therefore , this leaves at least bits, which are used to hold the bits relocated from the master and a pointer to the master. We call this representation the compact representation. A container may be compact, i.e., in the compact representation, without being a slave (Fig. 1(c)). Then, instead of the data relocated from a master, it stores two iteration pointers and a null pointer.
Using the algorithm of Lemma 3.3(b) with and , we can test in constant time whether a vertex located in a compact container is gray by checking whether its number within the container occurs in the gray list of the container. If not, we can subsequently determine the color of the vertex in constant time from the black-and-white vector. Similarly, we can change the color of a given vertex in constant time. This may involve creating a gap for the new vertex in the gray list or, conversely, closing such a gap, which is easily accomplished with a constant number of bitwise Boolean and shift operations. It is also easy to see that we can iterate over the gray vertices in time.
If a color change increases the number of gray vertices in a compact container to , the container must be converted to the regular representation. For this it will be convenient if the black-and-white vector stores the least significant bits of the vertex colors not in their natural order, but in the shuffled order obtained by placing the first half of the bits, in the natural order, in the odd-numbered positions of the black-and-white vector and the last half in the even-numbered positions. With this convention, we can still read and update vertex colors in constant time. We can also unshuffle the black-and-white vector in constant time, creating 1-bit gaps for the most significant bits, by separating the bits in the odd-numbered positions from those in the even-numbered positions and concatenating the two sequences. Subsequently each most significant bit is set to be the complement of its corresponding least significant bit to represent the colors white and black according to the loose representation. Going through the gray list, we can then introduce the gray colors one by one. Thus we can convert from the compact to the loose and from there to the regular representation in time. Conversely, if a container in the loose representation has fewer than gray vertices, it can be converted to the compact representation in time.
3.2 The In-Place Chain Technique for Containers
The overall organization of the containers follows the in-place chain technique [11, 8, 10]. By means of an integer equal to the number of compact containers, the sequence of containers is dynamically divided into a left part, consisting of , and a right part, . A regular container is a master if and only if it belongs to the left part, and a compact container is a slave if and only if it belongs to the right part. Thus the two representations shown on the left in Fig. 1 ((a) and (c)) can occur only in the left part, while the two representations shown on the right can occur only in the right part. In particular, note that every container in the left part has iteration pointers.
Call a container gray-free if no vertex located in the container is gray. The iteration pointers are used to join all containers in the left part, with the exception of the gray-free compact containers, into a doubly-linked iteration list whose first and last elements are stored in bits outside of the containers.
When an update of a vertex color causes a container to switch from the compact to the regular representation, decreases by 1, say from to . If , belongs to the left part before the switch and to the right part after the switch, i.e., in terms of Fig. 1, the switch is from (c) to (b). If , the switch is more complicated, in that it involves other containers. If (Fig. 1, (c) to (a)), becomes a master, whereas if (Fig. 1, (d) to (b)), stops being a slave. In both cases there now is a master without a slave, a situation that must be remedied. However, also switches, namely either from (a) to (b) or from (c) to (d). In the case “(a) to (b)” stops being a master, and its former slave can become the slave of . In the case “(c) to (d)” becomes a slave and can serve as the slave of . Thus in all cases masters and slaves can again be matched up appropriately. Altogether, the operation involves changing some pointers and moving some relocated data in at most four containers. After the conversion of , this takes constant time.
In some circumstances that still need to be specified, a container may switch from the regular to the compact representation, which causes to increase by 1, say from to . We can handle this situation similarly as above. If , the switch is from (b) to (c) in Fig. 1, and nothing more must be done. Otherwise, whether the switch is from (a) to (c) or from (b) to (d), there will be a slave without a master. Simultaneously switches either from (b) to (a) (it becomes the needed master) or from (d) to (c) (it stops being a slave, and its former master takes on the new slave). Again, after the conversion of , the operation can happen in constant time.
4 BFS Algorithms
4.1 The Basic Algorithm
To execute the first line of the abstract 3-color BFS algorithm with the vertex-color data structure developed in the previous section, we initialize the data structure as follows: All vertices are white, all containers are compact, but not slaves, all have empty gray lists, the iteration list is empty, and .
It was already described how to read and update vertex colors. If a color change causes a compact container in the left part to become gray-free, is shunted out of the iteration list. Conversely, if a compact container in the left part stops being gray-free, it is inserted at the end of the iteration list. The case in which a container enters or leaves the left part because of a change in is handled analogously. All of this can happen in constant time. The only exception is if a color change forces a container to switch from the compact to the regular representation, which takes time.
Recall that the abstract 3-color BFS algorithm alternates between exploration rounds, in which it iterates over the gray vertices and colors some of their white neighbors gray, and consolidation rounds, in which it iterates over the gray vertices and colors some of them black. Each iteration is realized by iterating over two lists of containers: The explicitly maintained iteration list and the implicit right list, which consists of the containers in that order. Each of the two iterations can be viewed as moving a pebble through the relevant list. Because the lists may change dynamically, the following rules apply: If a currently pebbled container is deleted from its list, the pebble is first moved to the successor of in the relevant list. If a pebble reaches the end of its list, it waits there for new containers that may be inserted at the end of the list. One of the at most two pebbled containers is the current container , whose gray vertices are enumerated as explained earlier. If is regular, this involves first converting it to the loose representation. Once all gray vertices in have been enumerated, stops being the current container. If it is in the loose representation, we attempt to convert it to the compact representation. If this fails because contains more than gray vertices, we instead convert it to the regular representation. Then the pebble on is moved to the list successor of , and one of the at most two containers that are now pebbled is chosen to be the new current container. The iteration ends when both pebbles are at the end of their respective lists.
Since every container that is not gray-free belongs either to the iteration list or to the right list, it is clear that each round enumerates all vertices that are gray at the beginning of the round (and maybe some that become gray in the course of the round). A container and its gray vertices may be enumerated twice, namely once as part of the iteration list and once as part of the right list. The BFS algorithm can tolerate this, and no vertex is enumerated more than twice within one round because moves in only one direction within the round. A vertex can be gray for at most (part of) four consecutive rounds, so the total number of vertex enumerations is . Therefore the total time spent on enumeration is , except possibly for the following two contributions to the running time: (1) Containers that are enumerated but turn out to be gray-free; (2) Conversions of containers between different representations. As for (1), every container concerned is regular or on the right side, i.e., the number of such containers is bounded by . Since the iteration converts all regular containers to the loose representation, the contribution of (1) is dominated by that of (2). And as for (2), since the number of other conversions is within a constant factor of the number of conversions to the regular representation, it suffices to bound the latter by . But before the first conversion of a container to the regular representation, vertices located in must become gray, and between two successive such conversions at least vertices in either change color or are enumerated. Since the number of color changes and of vertex enumerations is , the bound follows.
Theorem 4.1**.**
The BFS problem can be solved on directed or undirected graphs with vertices and edges in time with bits of working memory.
4.2 A Time-Space Tradeoff
In order to derive a time-space tradeoff from Theorem 4.1, we must take a slightly closer look at the data structure of Dodis et al. [5] behind Lemma 3.1. For a certain set whose elements can be represented in bits, a certain function that can be evaluated in constant time and a certain start value that can be computed in constant time, the preprocessing of the data structure serves to compute and store a table of , where , for integer , denotes -fold repeated application of . In addition, we need the powers , which are also assumed to be stored in . If we carry out the preprocessing but store and only for those values of that are divisible by for some given integer , the shortened table occupies only bits, and the rest of the BFS algorithm works with bits. Whenever the data structure of Section 3 is called upon to carry out an operation, it needs a constant number of entries of , which can be reconstructed from those in in time. This causes a slowdown of compared to an algorithm that has the full table at its disposal. Thus Theorem 4.1 generalizes as follows:
Theorem 4.2**.**
For every given , the BFS problem can be solved on directed or undirected graphs with vertices and edges in time with bits of working memory.
4.3 BFS with Bits
Suppose now that we are allowed only extra bits. Then, with notation as in the previous subsection, we can no longer afford to store the table of and . Instead we store only the two -bit quantities and 3 and compute and from them as needed. Concerning the latter, can be computed in time for arbitrary by a well-known method based on repeated squaring.
When the data structure of Dodis et al. [5] is used to represent an array with index set , , for , is associated with the node in a complete -node binary tree whose nodes are numbered in the manner of Heapsort, i.e., the root is 1 and the parent of every nonroot node is . Suppose that a node is of height in . Then we can access (read or update) in constant time after computing from , which takes time. In the worst case , so we can access with a slowdown of relative to an algorithm with access to the full table . This leads to the result of Theorem 4.2 for , i.e., time and extra bits. However, for most the height is much smaller than , which hints at a possible improvement.
For , let be the (total) degree of the vertex in the input graph. It is easy to see that the number of accesses to the color of in the course of the execution of the BFS algorithm is . The color of is located in the container , where , or in a slave with , and is in fact a big digit stored in , where is the array maintained with the data structure of Dodis et al. [5]. The depth of the node in the corresponding binary tree is exactly , and it is not difficult to see that its height is at most . Therefore the running time of the complete BFS algorithm is .
If , . Thus if the vertex degrees form a nondecreasing sequence, the running time is . Since if for some , the same is true if for some fixed . Informally, the latter condition is satisfied if is approximately regular. In particular, it is satisfied if the ratio of the maximum degree in to the average degree is (at most) polylogarithmic in .
The reference list from the paper itself. Each links out to its DOI / PubMed record.
- 1[1] D. Angluin and L. G. Valiant. Fast probabilistic algorithms for Hamiltonian circuits and matchings. J. Comput. Syst. Sci. , 18(2):155–193, 1979.
- 2[2] Niranka Banerjee, Sankardeep Chakraborty, and Venkatesh Raman. Improved space efficient algorithms for BFS, DFS and applications. In Proc. 22nd International Conference on Computing and Combinatorics (COCOON 2016) , volume 9797 of LNCS , pages 119–130. Springer, 2016.
- 3[3] Niranka Banerjee, Sankardeep Chakraborty, Venkatesh Raman, and Srinivasa Rao Satti. Space efficient linear time algorithms for BFS, DFS and applications. Theory Comput. Syst. , 62(8):1736–1762, 2018.
- 4[4] Greg Barnes, Jonathan F. Buss, Walter L. Ruzzo, and Baruch Schieber. A sublinear space, polynomial time algorithm for directed s 𝑠 s - t 𝑡 t connectivity. SIAM J. Comput. , 27(5):1273–1282, 1998.
- 5[5] Yevgeniy Dodis, Mihai Pǎtraşcu, and Mikkel Thorup. Changing base without losing space. In Proc. 42nd ACM Symposium on Theory of Computing (STOC 2010) , pages 593–602. ACM, 2010.
- 6[6] Amr Elmasry, Torben Hagerup, and Frank Kammer. Space-efficient basic graph algorithms. In Proc. 32nd International Symposium on Theoretical Aspects of Computer Science (STACS 2015) , volume 30 of LIP Ics , pages 288–301. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2015.
- 7[7] Torben Hagerup. Sorting and searching on the word RAM. In Proc. 15th Annual Symposium on Theoretical Aspects of Computer Science (STACS 1998) , volume 1373 of LNCS , pages 366–398. Springer, 1998.
- 8[8] Torben Hagerup. Small uncolored and colored choice dictionaries. Computing Research Repository (Co RR) , abs/1809.07661 [cs.DS], 2018.
