Movatterモバイル変換


[0]ホーム

URL:


nextuppreviouscontents
Next:7.3 Discussion and Exercises Up:7. Random Binary Search Previous:7.1 Random Binary Search  Contents

Subsections


7.2Treap: A Randomized Binary Search Tree

The problem with random binary search trees is, of course, that they arenot dynamic. They don't support the$ \mathtt{add(x)}$ or$ \mathtt{remove(x)}$ operationsneeded to implement theSSet interface. In this section we describea data structure called aTreap that uses Lemma 7.1 to implementtheSSet interface.7.2

A node in aTreap is like a node in aBinarySearchTree in that it hasa data value,$ \mathtt{x}$, but it also contains a unique numericalpriority,$ \mathtt{p}$, that is assigned at random:

    class Node<T> extends BinarySearchTree.BSTNode<Node<T>,T> {        int p;    }
In addition to being a binary search tree, the nodes in aTreapalso obey theheap property:In other words, each node has a priority smaller than that of its twochildren. An example is shown in Figure 7.5.

Figure 7.5:An example of aTreap containing the integers$ 0,\ldots,9$. Each node,$ \mathtt{u}$, is illustrated as a box containing$ \ensuremath{\mathtt{u.x}},\ensuremath{\mathtt{u.p}}$.
\includegraphics{figs/treap}

The heap and binary search tree conditions together ensure that, oncethe key ($ \mathtt{x}$) and priority ($ \mathtt{p}$) for each node are defined, theshape of theTreap is completely determined. The heap property tells us thatthe node with minimum priority has to be the root,$ \mathtt{r}$, of theTreap.The binary search tree property tells us that all nodes with keys smallerthan$ \mathtt{r.x}$ are stored in the subtree rooted at$ \mathtt{r.left}$ and all nodeswith keys larger than$ \mathtt{r.x}$ are stored in the subtree rooted at$ \mathtt{r.right}$.

The important point about the priority values in aTreap is that theyare unique and assigned at random. Because of this, there aretwo equivalent ways we can think about aTreap. As defined above, aTreap obeys the heap and binary search tree properties. Alternatively,we can think of aTreap as aBinarySearchTree whose nodeswere added in increasing order of priority. For example, theTreapin Figure 7.5 can be obtained by adding the sequence of$ (\ensuremath{\mathtt{x}},\ensuremath{\mathtt{p}})$values

$\displaystyle \langle(3,1), (1,6), (0,9), (5,11), (4,14), (9,17), (7,22), (6,42), (8,49), (2,99)\rangle$

into aBinarySearchTree.

Since the priorities are chosen randomly, this is equivalent to taking arandom permutation of the keys -- in this case the permutation is

$\displaystyle \langle 3, 1, 0, 5, 9, 4, 7, 6, 8, 2 \rangle$

-- and adding these to aBinarySearchTree. But this means that theshape of a treap is identical to that of a random binary search tree.In particular, if we replace each key$ \mathtt{x}$ by its rank,7.3 then Lemma 7.1 applies.Restating Lemma 7.1 in terms ofTreaps, we have:

Lemma7..2  In aTreap that stores a set$ S$ of$ \mathtt{n}$ keys, the following statements hold:
  1. For any$ \ensuremath{\mathtt{x}}\in S$, the expected length of the search path for$ \mathtt{x}$ is$ H_{r(\ensuremath{\mathtt{x}})+1} + H_{\ensuremath{\mathtt{n}}-r(\ensuremath{\mathtt{x}})} - O(1)$.
  2. For any$ \ensuremath{\mathtt{x}}\not\in S$, the expected length of the search path for$ \mathtt{x}$ is$ H_{r(\ensuremath{\mathtt{x}})} + H_{\ensuremath{\mathtt{n}}-r(\ensuremath{\mathtt{x}})}$.
Here,$ r(\ensuremath{\mathtt{x}})$ denotes the rank of$ \mathtt{x}$ in the set$ S\cup\{\ensuremath{\mathtt{x}}\}$.

Again, we emphasize that the expectation in Lemma 7.2 is takenover the random choices of the priorities for each node. It does notrequire any assumptions about the randomness in the keys.

Lemma 7.2 tells us thatTreaps can implement the$ \mathtt{find(x)}$operation efficiently. However, the real benefit of aTreap is thatit can support the$ \mathtt{add(x)}$ and$ \mathtt{delete(x)}$ operations. Todo this, it needs to perform rotations in order to maintain the heap property. Refer to Figure 7.6.Arotation in a binarysearch tree is a local modification that takes a parent$ \mathtt{u}$ of a node$ \mathtt{w}$and makes$ \mathtt{w}$ the parent of$ \mathtt{u}$, while preserving the binary search treeproperty. Rotations come in two flavours:left orrightdepending on whether$ \mathtt{w}$ is a right or left child of$ \mathtt{u}$, respectively.

Figure 7.6:Left and right rotations in a binary search tree.
\includegraphics{figs/rotation}

The code that implements this has to handle these two possibilitiesand be careful of a boundarycase (when$ \mathtt{u}$ is the root) so the actual code is a little longer thanFigure 7.6 would lead a reader to believe:

    void rotateLeft(Node u) {        Node w = u.right;        w.parent = u.parent;        if (w.parent != nil) {            if (w.parent.left == u) {                w.parent.left = w;            } else {                w.parent.right = w;            }        }        u.right = w.left;        if (u.right != nil) {            u.right.parent = u;        }        u.parent = w;        w.left = u;        if (u == r) { r = w; r.parent = nil; }    }        void rotateRight(Node u) {        Node w = u.left;        w.parent = u.parent;        if (w.parent != nil) {            if (w.parent.left == u) {                w.parent.left = w;            } else {                w.parent.right = w;            }        }        u.left = w.right;        if (u.left != nil) {            u.left.parent = u;        }        u.parent = w;        w.right = u;        if (u == r) { r = w; r.parent = nil; }    }
In terms of theTreap data structure, the most important property of arotation is that the depth of$ \mathtt{w}$ decreases by one while the depth of$ \mathtt{u}$increases by one.

Using rotations, we can implement the$ \mathtt{add(x)}$ operation as follows:We create a new node,$ \mathtt{u}$, and assign$ \mathtt{u.x=x}$ and pick a random valuefor$ \mathtt{u.p}$. Next we add$ \mathtt{u}$ using the usual$ \mathtt{add(x)}$ algorithmfor aBinarySearchTree, so that$ \mathtt{u}$ is now a leaf of theTreap.At this point, ourTreap satisfies the binary search tree property,but not necessarily the heap property. In particular, it may be thecase that$ \mathtt{u.parent.p > u.p}$. If this is the case, then we perform arotation at node$ \mathtt{w}$=$ \mathtt{u.parent}$ so that$ \mathtt{u}$ becomes the parent of$ \mathtt{w}$.If$ \mathtt{u}$ continues to violate the heap property, we will have to repeat this, decreasing$ \mathtt{u}$'s depth by one every time, until$ \mathtt{u}$ either becomes the root or$ \ensuremath{\mathtt{u.parent.p}} < \ensuremath{\mathtt{u.p}}$.

    boolean add(T x) {        Node<T> u = newNode();        u.x = x;        u.p = rand.nextInt();        if (super.add(u)) {            bubbleUp(u);            return true;        }        return false;    }    void bubbleUp(Node<T> u) {        while (u.parent != nil && u.parent.p > u.p) {            if (u.parent.right == u) {                rotateLeft(u.parent);            } else {                rotateRight(u.parent);            }        }        if (u.parent == nil) {            r = u;        }    }
An example of an$ \mathtt{add(x)}$ operation is shown in Figure 7.7.

Figure 7.7:Adding the value 1.5 into theTreap from Figure 7.5.
\includegraphics{figs/treap-insert-a}
\includegraphics{figs/treap-insert-b}
\includegraphics{figs/treap-insert-c}

The running time of the$ \mathtt{add(x)}$ operation is given by the time ittakes to follow the search path for$ \mathtt{x}$ plus the number of rotationsperformed to move the newly-added node,$ \mathtt{u}$, up to its correct locationin theTreap. By Lemma 7.2, the expected length of thesearch path is at most$ 2\ln \ensuremath{\mathtt{n}}+O(1)$. Furthermore, each rotationdecreases the depth of$ \mathtt{u}$. This stops if$ \mathtt{u}$ becomes the root, sothe expected number of rotations cannot exceed the expected length ofthe search path. Therefore, the expected running time of the$ \mathtt{add(x)}$operation in aTreap is$ O(\log \ensuremath{\mathtt{n}})$. (Exercise 7.5asks you to show that the expected number of rotations performed duringan addition is actually only$ O(1)$.)

The$ \mathtt{remove(x)}$ operation in aTreap is the opposite of the$ \mathtt{add(x)}$operation. We search for the node,$ \mathtt{u}$, containing$ \mathtt{x}$ and then performrotations to move$ \mathtt{u}$ downwards until it becomes a leaf and then wesplice$ \mathtt{u}$ from theTreap. Notice that, to move$ \mathtt{u}$ downwards, we canperform either a left or right rotation at$ \mathtt{u}$, which will replace$ \mathtt{u}$with$ \mathtt{u.right}$ or$ \mathtt{u.left}$, respectively.The choice is made by the first of the following that apply:

  1. If$ \mathtt{u.left}$ and$ \mathtt{u.right}$ are both$ \mathtt{null}$, then$ \mathtt{u}$ is a leaf and no rotation is performed.
  2. If$ \mathtt{u.left}$ (or$ \mathtt{u.right}$) is$ \mathtt{null}$, then perform a right (or left, respectively) rotation at$ \mathtt{u}$.
  3. If$ \ensuremath{\mathtt{u.left.p}} < \ensuremath{\mathtt{u.right.p}}$ (or$ \ensuremath{\mathtt{u.left.p}} > \ensuremath{\mathtt{u.right.p}})$, then perform a right rotation (or left rotation, respectively) at$ \mathtt{u}$.
These three rules ensure that theTreap doesn't become disconnected and that the heap property is restored once$ \mathtt{u}$ is removed.
    boolean remove(T x) {        Node<T> u = findLast(x);        if (u != nil && compare(u.x, x) == 0) {            trickleDown(u);            splice(u);            return true;        }        return false;    }    void trickleDown(Node<T> u) {        while (u.left != nil || u.right != nil) {            if (u.left == nil) {                rotateLeft(u);            } else if (u.right == nil) {                rotateRight(u);            } else if (u.left.p < u.right.p) {                rotateRight(u);            } else {                rotateLeft(u);            }            if (r == u) {                r = u.parent;            }        }    }
An example of the$ \mathtt{remove(x)}$ operation is shown in Figure 7.8.
Figure 7.8:Removing the value 9 from theTreap in Figure 7.5.
\includegraphics{figs/treap-delete-a}
\includegraphics{figs/treap-delete-b}
\includegraphics{figs/treap-delete-c}
\includegraphics{figs/treap-delete-d}

The trick to analyze the running time of the$ \mathtt{remove(x)}$ operation isto notice that this operation is the reverse of the$ \mathtt{add(x)}$ operation.In particular, if we were to reinsert$ \mathtt{x}$, using the same priority$ \mathtt{u.p}$,then the$ \mathtt{add(x)}$ operation would do exactly the same number of rotationsand would restore theTreap to exactly the same state it was in beforethe$ \mathtt{remove(x)}$ operation took place. (Reading from bottom-to-top,Figure 7.8 illustrates the addition of the value 9 into aTreap.) This means that the expected running time of the$ \mathtt{remove(x)}$on aTreap of size$ \mathtt{n}$ is proportional to the expected running timeof the$ \mathtt{add(x)}$ operation on aTreap of size$ \ensuremath{\mathtt{n}}-1$. We concludethat the expected running time of$ \mathtt{remove(x)}$ is$ O(\log \ensuremath{\mathtt{n}})$.

7.2.1 Summary

The following theorem summarizes the performance of theTreap datastructure:

Theorem7..2  ATreap implements theSSet interface. ATreap supportsthe operations$ \mathtt{add(x)}$,$ \mathtt{remove(x)}$, and$ \mathtt{find(x)}$ in$ O(\log \ensuremath{\mathtt{n}})$expected time per operation.

It is worth comparing theTreap data structure to theSkiplistSSetdata structure. Both implement theSSet operations in$ O(\log \ensuremath{\mathtt{n}})$expected time per operation. In both data structures,$ \mathtt{add(x)}$ and$ \mathtt{remove(x)}$involve a search and then a constant number of pointer changes(see Exercise 7.5 below). Thus, for both thesestructures, the expected length of the search path is the critical valuein assessing their performance. In aSkiplistSSet, the expected lengthof a search path is

$\displaystyle 2\log \ensuremath{\mathtt{n}} + O(1) \enspace ,$

In aTreap, the expected length of a search path is

$\displaystyle 2\ln \ensuremath{\mathtt{n}} +O(1) \approx 1.386\log \ensuremath{\mathtt{n}} + O(1) \enspace .$

Thus, the search paths in aTreap are considerably shorter and thistranslates into noticeably faster operations onTreaps thanSkiplists.Exercise 4.7 in Chapter 4 shows how theexpected length of the search path in aSkiplist can be reduced to

$\displaystyle e\ln \ensuremath{\mathtt{n}} + O(1) \approx 1.884\log \ensuremath{\mathtt{n}} + O(1)$

by using biased coin tosses. Even with this optimization, the expectedlength of search paths in aSkiplistSSet is noticeably longer than inaTreap.



Footnotes

... interface.7.2
The namesTreap comes from the factthat this data structure is simultaneously a binary searchtree(Section 6.2) and a heap (Chapter 10).
... rank,7.3
Therank of an element$ \mathtt{x}$ in a set$ S$ of elements is the number ofelements in$ S$ that are less than$ \mathtt{x}$.

nextuppreviouscontents
Next:7.3 Discussion and Exercises Up:7. Random Binary Search Previous:7.1 Random Binary Search  Contents
opendatastructures.org
[8]ページ先頭

©2009-2025 Movatter.jp