Order-maintenance problem

From Wikipedia, the free encyclopedia
Jump to: navigation, search

In Computer Science the Order-Maintenance Problem involves maintaining a totally ordered set supporting the following operations:

  • insert(X, Y), which inserts X immediately after Y in the total order;
  • order(X, Y), which determines if X precedes Y in the total order; and
  • delete(X), which removes X from the set.

The first data structure for order-maintenance was given by Dietz in 1982.[1] This data structure supports insert(X, Y) in O(\log n) amortized time and order(X, Y) in constant time but does not support deletion. Tsakalidis published a data structure in 1984 based on BB[α] trees with the same performance bounds that supports deletion in O(\log n) and showed how indirection can be used to improve insertion and deletion performance to O(1) amortized time.[2] In 1987 Dietz and Sleator published the first data structure supporting all operations in worst-case constant time.[3]

Efficient data structures for order-maintenance have applications in many areas, including data structure persistence,[4] graph algorithms[5][6] and fault-tolerant data structures.[7]

List-labeling[edit]

A problem related to the order-maintenance problem is the list-labeling problem in which instead of the order(X, Y) operation the solution must maintain an assignment of labels from a universe of integers \{1, 2, \ldots, u\} to the elements of the set such that X precedes Y in the total order if and only if X is assigned a lesser label than Y. It must also support an operation label(X) returning the label of any node X. Note that order(X, Y) can be implemented simply by comparing label(X) and label(Y) so that any solution to the list-labeling problem immediately gives one to the order-maintenance problem. In fact, most solutions to the order-maintenance problem are solutions to the list-labeling problem augmented with a level of data structure indirection to improve performance. We will see an example of this below.

For efficiency, it is desirable for the size u of the universe be bounded in the number of elements n stored in the data structure. In the case where u is required to be linear in n the problem is known as the packed-array maintenance or dense sequential file maintenance problem. Consider the elements as entries in a file and the labels as giving the addresses where each element is stored. Then an efficient solution to the packed-array maintenance problem would allow efficient insertions and deletions of entries into the middle of a file with no asymptotic space overhead.[8][9][10][11][12] This usage has recent applications in cache-oblivious data structures[13] and optimal worst-case in-place sorting.[14]

However, under some restrictions, \Omega(\log^2 n) lower bounds have been found on the performance of insertion in solutions of the list-labeling problem with linear universes[15] whereas we will see below that a solution with a polynomial universe can perform insertions in O(\log n) time.

List-labeling and binary search trees[edit]

An example of path labels as described in the order-maintenance page.
The path label of X in this binary tree is 0221, which is the base 3 representation of the integer 25.

List-labeling in a universe of size polynomial in the number n of elements in the total order is connected to the problem of maintaining balance in a binary search tree. Note that every node X of a binary search tree is implicitly labeled with an integer that corresponds to its path from the root of the tree. We call this integer the path label of X and define it as follows. Let \sigma be the sequence of left and right descents in this path. For example, \sigma = (\text{left}, \text{right},
\text{right}) if X is the right child of the right child of the left child of the root of the tree. Then X is labeled with the integer whose base 3 representation is given by replacing every occurrence of \text{left} in \sigma with 0, replacing every occurrence of \text{right} in \sigma with 2 and appending 1 to the end of the resulting string. Then in the previous example, the path label of X is 02213 which is equal to 25 in base 10. Note that path labels preserve tree-order and so can be used to answer order queries in constant time.

If the tree has height h then these integers come from the universe \{1, 2, \ldots, 3^{h+1}-2\}. Then if the tree is self-balancing so that it maintains a height no greater than c\log n then the size of the universe is polynomial in n.

Therefore, the list-labeling problem can be solved by maintaining a balanced binary search tree on the elements in the list augmented with path labels for each node. However, since every rebalancing operation of the tree would have to also update these path labels, not every self-balancing tree data structure is suitable for this application. Note, for example, that rotating a node with a subtree of size k, which can be done in constant time under usual circumstances, requires \Omega(k) path label updates. In particular, if the node being rotated is the root then the rotation would take time linear in the size of the whole tree. With that much time the entire tree could be rebuilt. We will see below that there are self-balancing binary search tree data structures that cause an appropriate number of label updates during rebalancing.

Data structure[edit]

The list-labeling problem can be solved with a universe of size polynomial in the number of elements n by augmenting a scapegoat tree with the path labels described above. Scapegoat trees do all of their rebalancing by rebuilding subtrees. Since it takes \Omega(k) time to rebuild a subtree of size k, relabeling that subtree in O(k) time after it is rebuilt does not change the asymptotic performance of the rebalancing operation.

Order[edit]

Given two nodes X and Y, order(X, Y) determines their order by comparing their path labels.

Insert[edit]

Given a new node for X and a pointer to the node Y, insert(X, Y) inserts X immediately after Y in the usual way. If a rebalancing operation is required, the appropriate subtree is rebuilt, as usual for a scapegoat tree. Then that subtree is traversed depth first and the path labels of each of its nodes is updated. As described above, this asymptotically takes no longer than the usual rebuilding operation.

Delete[edit]

Deletion is performed similarly to insertion. Given the node X to be deleted, delete(X) removes X as usual. Any subsequent rebuilding operation is followed by a relabeling of the rebuilt subtree.

Analysis[edit]

It follows from the argument above about the rebalancing performance of a scapegoat tree augmented with path labels that the insertion and deletion performance of this data structure are asymptotically no worse than in a regular scapegoat tree. Then, since insertions and deletions take O(\log n) amortized time in scapegoat trees, the same holds for this data structure.

Furthermore, since a scapegoat tree with parameter α maintains a height of at most \log_{1/\alpha}n + 1, the path labels have size at most 3^{\log_{1/\alpha}n + 2}-2 \le
9n^{\frac{1}{\log_3(1/\alpha)}}. For the typical value of \alpha=\tfrac{2}{3} then the labels are at most 9n^3.

Of course, the order of two nodes can be determined in constant time by comparing their labels. A closer inspection shows that this holds even for large n. Specifically, if the word size of the machine is w bits, then typically it can address at most 2^w nodes so that n < 2^w. It follows that the universe has size at most 9\cdot 2^{3w} and so that the labels can be represented with a constant number of (at most 4 +
3w) bits.

Lower bound on list-labeling[edit]

It has been shown that any solution to the list-labeling problem with a universe polynomial in the number of elements will have insertion and deletion performance no better than \Omega(\log
n).[16] Then, for list-labeling, the above solution is asymptotically optimal. Incidentally, this also proves an \Omega(\log n) lower bound on the amortized rebalancing time of an insertion or deletion in a scapegoat tree.

However, this lower bound does not apply to the order-maintenance problem and, as stated above, there are data structures that give worst-case constant time performance on all order-maintenance operations.

O(1) amortized insertion via indirection[edit]

Indirection is a technique used in data structures in which a problem is split into multiple levels of a data structure in order to improve efficiency. Typically, a problem of size n is split into n/\log n problems of size \log n. For example, this technique is used in y-fast tries. This strategy also works to improve the insertion and deletion performance of the data structure described above to constant amortized time. In fact, this strategy works for any solution of the list-labeling problem with O(\log n) amortized insertion and deletion time.

Depiction of indirection in a tree based solution to the order-maintenance problem.
The order-maintenance data structure with indirection. The total order elements are stored in O(N/\log N) contiguous sublists of size O(\log N), each of which has a representative in the scapegoat tree.

The new data structure is completely rebuilt whenever it grows too large or too small. Let N be the number of elements of the total order when it was last rebuilt. The data structure is rebuilt whenever the invariant \tfrac{N}{3}\le n\le 2N is violated by an insertion or deletion. Since rebuilding can be done in linear time this does not affect the amortized performance of insertions and deletions.

During the rebuilding operation, the N elements of the total order are split into O(N/\log N) contiguous sublists, each of size \Omega(\log N). A path-labeled scapegoat tree is constructed on a set of nodes representing each of the sublists in their original list order. For each sublist a doubly-linked of its elements is built storing with each element a pointer to its representative in the tree as well as a local integer label. These local labels are independent of the labels used in the tree and are used to compare any two elements of the same sublist. The elements of a sublist are given the local labels \log N, 2\log
N, \ldots, \log^2 N, \ldots, in their original list order.

Order[edit]

Given the sublist nodes X and Y, order(X, Y) can be answered by first checking if the two nodes are in the same sublist. If so, their order can be determined by comparing their local labels. Otherwise the path labels of their representatives in the tree are compared. This takes constant time.

Insert[edit]

Given a new sublist node for X and a pointer to the sublist node Y, insert(X, Y) inserts X immediately after Y in the sublist of Y. If X is inserted at the end of the sublist, it is given the local label \ell(Y) + \log N, where \ell(Y) is the local label of Y; otherwise, if possible, it is labeled with the floor of the average of the local labels of its two neighbours. This easy case takes constant time.

In the hard case, the neighbours of X have contiguous local labels and the sublist has to be rebuilt. However, in this case at least \log N - 1 elements have been added to the sublist since it was first built. Then we can afford to spend a linear amount of time in the size of the sublist to rebuild it and possibly split it into smaller sublists without affecting the amortized cost of insertion by any more than a constant.

If the sublist has size k then we split it into O(k/\log N) contiguous sublists of size O(\log
N), locally labeling each new sublist as described above and pointing each element of a sublist to a new representative node to be inserted into the tree. It takes O(k) time to construct the sublists. Since we do not allow empty sublists, there are at most n\le 2N of them and so a representative can be inserted into the tree in O(\log N) time. Hence, it takes O(k) time to insert all of the new representatives into the tree.

Delete[edit]

Given a sublist node X to be deleted, delete(X) simply removes X from its sublist in constant time. If this leaves the sublist empty, then we need to remove the representative of the sublist from the tree. Since at least \Omega(\log N) elements were deleted from the sublist since it was first built we can afford to spend the O(\log N) time it takes to remove the representative without affecting the amortized cost of deletion by any more than a constant.

See also[edit]

References[edit]

  1. ^ Dietz, Paul F. (1982), "Maintaining order in a linked list", Proceedings of the 14th Annual ACM Symposium on Theory of Computing (STOC '82), New York, NY, USA: ACM, pp. 122–127, doi:10.1145/800070.802184 .
  2. ^ Tsakalidis, Athanasios K. (1984), "Maintaining order in a generalized linked list", Acta Informatica 21 (1): 101–112, doi:10.1007/BF00289142, MR 747173 .
  3. ^ Dietz, P.; Sleator, D. (1987), "Two algorithms for maintaining order in a list", Proceedings of the 19th Annual ACM Symposium on Theory of Computing (STOC '87), New York, NY, USA: ACM, pp. 365–372, doi:10.1145/28395.28434 . Full version, Tech. Rep. CMU-CS-88-113, Carnegie Mellon University, 1988.
  4. ^ Driscoll, James R.; Sarnak, Neil; Sleator, Daniel D.; Tarjan, Robert E. (1989), "Making data structures persistent", Journal of Computer and System Sciences 38 (1): 86–124, doi:10.1016/0022-0000(89)90034-2, MR 990051 .
  5. ^ Eppstein, David; Galil, Zvi; Italiano, Giuseppe F.; Nissenzweig, Amnon (1997), "Sparsification—a technique for speeding up dynamic graph algorithms", Journal of the ACM 44 (5): 669–696, doi:10.1145/265910.265914, MR 1492341 .
  6. ^ Katriel, Irit; Bodlaender, Hans L. (2006), "Online topological ordering", ACM Transactions on Algorithms 2 (3): 364–379, doi:10.1145/1159892.1159896, MR 2253786 .
  7. ^ Aumann, Yonatan; Bender, Michael A. (1996), "Fault tolerant data structures", Proceedings of the 37th Annual Symposium on Foundations of Computer Science (FOCS 1996), pp. 580–589, doi:10.1109/SFCS.1996.548517 .
  8. ^ Itai, Alon; Konheim, Alan; Rodeh, Michael (1981), "A sparse table implementation of priority queues", Automata, Languages and Programming: Eighth Colloquium Acre (Akko), Israel July 13–17, 1981, Lecture Notes in Computer Science 115, pp. 417–431, doi:10.1007/3-540-10843-2_34 .
  9. ^ Willard, Dan E. (1981), Inserting and deleting records in blocked sequential files, Technical Report TM81-45193-5, Bell Laboratories .
  10. ^ Willard, Dan E. (1982), "Maintaining dense sequential files in a dynamic environment (Extended Abstract)", Proceedings of the 14th ACM Symposium on Theory of Computing (STOC '82), New York, NY, USA: ACM, pp. 114–121, doi:10.1145/800070.802183 .
  11. ^ Willard, Dan E. (1986), "Good worst-case algorithms for inserting and deleting records in dense sequential files", Proceedings of the 1986 ACM SIGMOD International Conference on Management of Data (SIGMOD '86), SIGMOD Record 15(2), New York, NY, USA: ACM, pp. 251–260, doi:10.1145/16894.16879 .
  12. ^ Willard, Dan E. (1992), "A density control algorithm for doing insertions and deletions in a sequentially ordered file in a good worst-case time", Information and Computation 97 (2): 150–204, doi:10.1016/0890-5401(92)90034-D .
  13. ^ Bender, Michael A.; Demaine, Erik D.; Farach-Colton, Martin (2005), "Cache-oblivious B-trees", SIAM Journal on Computing 35 (2): 341–358, doi:10.1137/S0097539701389956, MR 2191447 .
  14. ^ Franceschini, Gianni; Geffert, Viliam (2005), "An in-place sorting with O(n log n) comparisons and O(n) moves", Journal of the ACM 52 (4): 515–537, doi:10.1145/1082036.1082037, MR 2164627 .
  15. ^ Dietz, Paul F.; Zhang, Ju (1990), "Lower bounds for monotonic list labeling", SWAT 90 (Bergen, 1990), Lecture Notes in Computer Science 447, Berlin: Springer, pp. 173–180, doi:10.1007/3-540-52846-6_87, MR 1076025 .
  16. ^ Dietz, Paul F.; Seiferas, Joel I.; Zhang, Ju (1994), "A tight lower bound for on-line monotonic list labeling", Algorithm theory—SWAT '94 (Aarhus, 1994), Lecture Notes in Computer Science 824, Berlin: Springer, pp. 131–142, doi:10.1007/3-540-58218-5_12, MR 1315312 .

External links[edit]