</p></div><divclass="section"><divclass="titlepage"><div><div><h4class="title"><aid="pbds.design.concepts.associative_semantics"></a>Map and Set Semantics</h4></div></div></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="concepts.associative_semantics.set_vs_map"></a>
</p></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="concepts.associative_semantics.multi"></a>Alternatives to <codeclass="classname">std::multiset</code> and <codeclass="classname">std::multimap</code></h5></div></div></div><p>
</p><divclass="figure"><aid="id-1.3.5.9.4.3.3.3.14"></a><pclass="title"><strong>Figure22.8.Non-unique Mapping Standard Containers</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_embedded_lists_1.png"align="middle"alt="Non-unique Mapping Standard Containers"/></div></div></div><brclass="figure-break"/><p>
</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_embedded_lists_2.png"align="middle"alt="Effect of embedded lists in std::multimap"/></div></div></div><brclass="figure-break"/><p>
</p></div></div><divclass="section"><divclass="titlepage"><div><div><h4class="title"><aid="pbds.design.concepts.iterator_semantics"></a>Iterator Semantics</h4></div></div></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="concepts.iterator_semantics.point_and_range"></a>Point and Range Iterators</h5></div></div></div><p>
</p></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="concepts.iterator_semantics.both"></a>Distinguishing Point and Range Iterators</h5></div></div></div><p>When using this library, is necessary to differentiate
containers: iterators are synonymous with const iterators.</p><divclass="figure"><aid="id-1.3.5.9.4.3.4.3.5"></a><pclass="title"><strong>Figure22.11.Point Iterator Hierarchy</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_point_iterator_hierarchy.png"align="middle"alt="Point Iterator Hierarchy"/></div></div></div><brclass="figure-break"/><p>Note that point-type iterators in self-organizing containers
common use.</p></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="pbds.design.concepts.invalidation"></a>Invalidation Guarantees</h5></div></div></div><p>
can be cast to its base class (in this case <codeclass="classname">point_invalidation_guarantee</code>).
This means that this this hierarchy can be used easily using
standard metaprogramming techniques, by specializing on the
type of <codeclass="literal">invalidation_guarantee</code>.</p><p>
These types of problems were addressed, in a more general
setting, in <aclass="xref"href="policy_data_structures.html#biblio.meyers96more"title="More Effective C++: 35 New Ways to Improve Your Programs and Designs">[biblio.meyers96more]</a> - Item 2. In
our opinion, an invalidation-guarantee hierarchy would solve
these problems in all container types - not just associative
</p><divclass="figure"><aid="id-1.3.5.9.4.3.5.7.4"></a><pclass="title"><strong>Figure22.13.Container Tag Hierarchy</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_container_tag_hierarchy.png"align="middle"alt="Container Tag Hierarchy"/></div></div></div><brclass="figure-break"/><p>
</p></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="concepts.genericity.traits"></a>Traits</h5></div></div></div><p></p><p>Additionally, a traits mechanism can be used to query a
</pre><p>The parameters have the following meaning:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p><codeclass="classname">Key</code> is the key type.</p></li><liclass="listitem"><p><codeclass="classname">Mapped</code> is the mapped-policy.</p></li><liclass="listitem"><p><codeclass="classname">Hash_Fn</code> is a key hashing functor.</p></li><liclass="listitem"><p><codeclass="classname">Eq_Fn</code> is a key equivalence functor.</p></li><liclass="listitem"><p><codeclass="classname">Comb_Hash_Fn</code> is a range-hashing_functor;
collision-chaining container, except for the following.</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p><codeclass="classname">Comb_Probe_Fn</code> describes how to transform a probe
sequence into a sequence of positions within the table.</p></li><liclass="listitem"><p><codeclass="classname">Probe_Fn</code> describes a probe sequence policy.</p></li></ol></div><p>Some of the default template values depend on the values of
other parameters, and are explained below.</p></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="container.hash.details"></a>Details</h5></div></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.hash.details.hash_policies"></a>Hash Policies</h6></div></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="details.hash_policies.general"></a>General</h6></div></div></div><p>Following is an explanation of some functions which hashing
involves. The graphic below illustrates the discussion.</p><divclass="figure"><aid="id-1.3.5.9.4.4.2.3.2.2.3"></a><pclass="title"><strong>Figure22.14.Hash functions, ranged-hash functions, and
range-hashing functions</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_hash_ranged_hash_range_hashing_fns.png"align="middle"alt="Hash functions, ranged-hash functions, and range-hashing functions"/></div></div></div><brclass="figure-break"/><p>Let U be a domain (e.g., the integers, or the
strings of 3 characters). A hash-table algorithm needs to map
elements of U "uniformly" into the range [0,..., m -
1] (where m is a non-negative integral value, and
is, in general, time varying). I.e., the algorithm needs
a ranged-hash function</p><p>
f : U × Z<sub>+</sub> → Z<sub>+</sub>
</p><p>such that for any u in U ,</p><p>0 ≤ f(u, m) ≤ m - 1</p><p>and which has "good uniformity" properties (say
<aclass="xref"href="policy_data_structures.html#biblio.knuth98sorting"title="The Art of Computer Programming - Sorting and Searching">[biblio.knuth98sorting]</a>.)
One
common solution is to use the composition of the hash
function</p><p>h : U → Z<sub>+</sub> ,</p><p>which maps elements of U into the non-negative
i.e., for any r in Z<sub>+</sub>,</p><p>0 ≤ g(r, m) ≤ m - 1</p><p>The resulting ranged-hash function, is</p><divclass="equation"><aid="id-1.3.5.9.4.4.2.3.2.2.15"></a><pclass="title"><strong>Equation22.1.Ranged Hash Function</strong></p><divclass="equation-contents"><spanclass="mathphrase">
positions.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="details.hash_policies.range"></a>Range Hashing</h6></div></div></div><p>Some common choices for range-hashing functions are the
division, multiplication, and middle-square methods (<aclass="xref"href="policy_data_structures.html#biblio.knuth98sorting"title="The Art of Computer Programming - Sorting and Searching">[biblio.knuth98sorting]</a>), defined
</span></div></div><brclass="equation-break"/><p>g(r, m) = ⌈ u/v ( a r mod v ) ⌉</p><p>and</p><p>g(r, m) = ⌈ u/v ( r<sup>2</sup> mod v ) ⌉</p><p>respectively, for some positive integrals u and
m is a power of 2), i.e.,</p><divclass="equation"><aid="id-1.3.5.9.4.4.2.3.2.3.9"></a><pclass="title"><strong>Equation22.3.Division via Prime Modulo</strong></p><divclass="equation-contents"><spanclass="mathphrase">
</span></div></div><brclass="equation-break"/><p>and</p><divclass="equation"><aid="id-1.3.5.9.4.4.2.3.2.3.11"></a><pclass="title"><strong>Equation22.4.Division via Bit Mask</strong></p><divclass="equation-contents"><spanclass="mathphrase">
Dinkumware's implementation.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="details.hash_policies.ranged"></a>Ranged Hash</h6></div></div></div><p>In cases it is beneficial to allow the
client to directly specify a ranged-hash hash function. It is
true, that the writer of the ranged-hash function cannot rely
on the values of m having specific numerical properties
suitable for hashing (in the sense used in <aclass="xref"href="policy_data_structures.html#biblio.knuth98sorting"title="The Art of Computer Programming - Sorting and Searching">[biblio.knuth98sorting]</a>), since
the values of m are determined by a resize policy with
possibly orthogonal considerations.</p><p>There are two cases where a ranged-hash function can be
superior. The firs is when using perfect hashing: the
second is when the values of m can be used to estimate
the "general" number of distinct values required. This is
described in the following.</p><p>Let</p><p>
s = [ s<sub>0</sub>,..., s<sub>t - 1</sub>]
</p><p>be a string of t characters, each of which is from
only the first k characters of the string, where</p><p>|S|<sup>k</sup> ≥ m ,</p><p>i.e., using the hash function</p><divclass="equation"><aid="id-1.3.5.9.4.4.2.3.2.4.12"></a><pclass="title"><strong>Equation22.6.
</span></div></div><brclass="equation-break"/><p>requiring scanning over only</p><p>k = log<sub>4</sub>( m )</p><p>characters.</p><p>Other more elaborate hash-functions might scan k
decomposed as per a ranged hash composed of hash and range hashing.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="details.hash_policies.implementation"></a>Implementation</h6></div></div></div><p>This sub-subsection describes the implementation of
hash-functor, <codeclass="classname">Hash_Fn</code> is instantiated by <codeclass="classname">null_type</code> , then <codeclass="classname">Comb_Hash_Fn</code> is taken to be
a ranged-hash function. The graphic below shows an <codeclass="function">insert</code> sequence
diagram. The user inserts an element (point A), the container
transforms the key into a position using the combining functor
(points B and C).</p><divclass="figure"><aid="id-1.3.5.9.4.4.2.3.2.5.3.6"></a><pclass="title"><strong>Figure22.16.Insert hash sequence diagram with a null policy</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_hash_range_hashing_seq_diagram2.png"align="middle"alt="Insert hash sequence diagram with a null policy"/></div></div></div><brclass="figure-break"/></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="hash_policies.implementation.probe"></a>
implementing range-hashing and probing functions:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p><codeclass="classname">direct_mask_range_hashing</code>
</p><divclass="figure"><aid="id-1.3.5.9.4.4.2.3.2.5.5.5"></a><pclass="title"><strong>Figure22.17.Hash policy class diagram</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_hash_policy_cd.png"align="middle"alt="Hash policy class diagram"/></div></div></div><brclass="figure-break"/></div></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.hash.details.resize_policies"></a>Resize Policies</h6></div></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="resize_policies.general"></a>General</h6></div></div></div><p>Hash-tables, as opposed to trees, do not naturally grow or
policies can be decomposed into orthogonal policies:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p>A size policy indicating how a hash table
exceeded).</p></li></ol></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="resize_policies.size"></a>Size Policies</h6></div></div></div><p>Size policies determine how a hash table changes size. These
implementation.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="resize_policies.trigger"></a>Trigger Policies</h6></div></div></div><p>Trigger policies determine when a hash table changes size.
be found with probability at most 1/m.</p><divclass="figure"><aid="id-1.3.5.9.4.4.2.3.3.4.7"></a><pclass="title"><strong>Figure22.18.Balls and bins</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_balls_and_bins.png"align="middle"alt="Balls and bins"/></div></div></div><brclass="figure-break"/><p>Denote the probability that a probe sequence of length
</p><p>where (a) follows from the Chernoff bound (<aclass="xref"href="policy_data_structures.html#biblio.motwani95random"title="Randomized Algorithms">[biblio.motwani95random]</a>). To
calculate the probability that some bin contains a probe
sequence greater than k, we note that the
l<sub>i</sub> are negatively-dependent
(<aclass="xref"href="policy_data_structures.html#biblio.dubhashi98neg"title="Balls and bins: A study in negative dependence">[biblio.dubhashi98neg]</a>)
- 1 ) <sup>2</sup> ) / 2 ) ,</p><p>where (a) follows from the fact that the Chernoff bound can
be applied to negatively-dependent variables (<aclass="xref"href="policy_data_structures.html#biblio.dubhashi98neg"title="Balls and bins: A study in negative dependence">[biblio.dubhashi98neg]</a>). Inserting the first probability
equation into the second one, and equating with 1/m, we
) .</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="resize_policies.impl"></a>Implementation</h6></div></div></div><p>This sub-subsection describes the implementation of the
access the policies' internals.</p><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="resize_policies.impl.decomposition"></a>Decomposition</h6></div></div></div><p>Each hash-based container is parametrized by a
inserted, and the policy notified (point I).</p><divclass="figure"><aid="id-1.3.5.9.4.4.2.3.3.5.3.6"></a><pclass="title"><strong>Figure22.19.Insert resize sequence diagram</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_insert_resize_sequence_diagram1.png"align="middle"alt="Insert resize sequence diagram"/></div></div></div><brclass="figure-break"/><p>In practice, a resize policy can be usually orthogonally
is parametrized by <codeclass="classname">Size_Policy</code> and
<codeclass="classname">Trigger_Policy</code>, derives <codeclass="classname">public</code>ly from
both, and acts as a standard delegate (<aclass="xref"href="policy_data_structures.html#biblio.gof"title="Design Patterns - Elements of Reusable Object-Oriented Software">[biblio.gof]</a>)
to these policies.</p><p>The two graphics immediately below show sequence diagrams
illustrating the interaction between the standard resize policy
and its trigger and size policies, respectively.</p><divclass="figure"><aid="id-1.3.5.9.4.4.2.3.3.5.3.9"></a><pclass="title"><strong>Figure22.20.Standard resize policy trigger sequence
diagram</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_insert_resize_sequence_diagram3.png"align="middle"alt="Standard resize policy size sequence diagram"/></div></div></div><brclass="figure-break"/></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="resize_policies.impl.predefined"></a>Predefined Policies</h6></div></div></div><p>The library includes the following
instantiations of size and trigger policies:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p><codeclass="classname">hash_load_check_resize_trigger</code>
or <codeclass="classname">hash_prime_size_policy</code>.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="resize_policies.impl.internals"></a>Controling Access to Internals</h6></div></div></div><p>There are cases where (controlled) access to resize
policies' internals is beneficial. E.g., it is sometimes
useful to query a hash-table for the table's actual size (as
opposed to its <codeclass="function">size()</code> - the number of values it
currently holds); it is sometimes useful to set a table's
initial size, externally resize it, or change load factors.</p><p>Clearly, supporting such methods both decreases the
encapsulation of hash-based containers, and increases the
diversity between different associative-containers' interfaces.
Conversely, omitting such methods can decrease containers'
flexibility.</p><p>In order to avoid, to the extent possible, the above
conflict, the hash-based containers themselves do not address
any of these questions; this is deferred to the resize policies,
which are easier to change or replace. Thus, for example,
neither <codeclass="classname">cc_hash_table</code> nor
<codeclass="classname">gp_hash_table</code>
contain methods for querying the actual size of the table; this
is deferred to <codeclass="classname">hash_standard_resize_policy</code>.</p><p>Furthermore, the policies themselves are parametrized by
template arguments that determine the methods they support
(
<aclass="xref"href="policy_data_structures.html#biblio.alexandrescu01modern"title="Modern C++ Design: Generic Programming and Design Patterns Applied">[biblio.alexandrescu01modern]</a>
shows techniques for doing so). <codeclass="classname">hash_standard_resize_policy</code>
is parametrized by <codeclass="classname">External_Size_Access</code> that
determines whether it supports methods for querying the actual
size of the table or resizing it. <codeclass="classname">hash_load_check_resize_trigger</code>
is parametrized by <codeclass="classname">External_Load_Access</code> that
determines whether it supports methods for querying or
modifying the loads. <codeclass="classname">cc_hash_max_collision_check_resize_trigger</code>
is parametrized by <codeclass="classname">External_Load_Access</code> that
determines whether it supports methods for querying the
load.</p><p>Some operations, for example, resizing a container at
run time, or changing the load factors of a load-check trigger
policy, require the container itself to resize. As mentioned
above, the hash-based containers themselves do not contain
these types of methods, only their resize policies.
Consequently, there must be some mechanism for a resize policy
to manipulate the hash-based container. As the hash-based
container is a subclass of the resize policy, this is done
through virtual methods. Each hash-based container has a
<codeclass="classname">do_resize</code> to resize the table.</p></div></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.hash.details.policy_interaction"></a>Policy Interactions</h6></div></div></div><p>
container. Following are some considerations.</p><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="policy_interaction.probesizetrigger"></a>probe/size/trigger</h6></div></div></div><p>Some combinations do not work well for probing containers.
exception in this case.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="policy_interaction.hashtrigger"></a>hash/trigger</h6></div></div></div><p>Some trigger policies are especially susceptible to poor
only once whether a resize is needed.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="policy_interaction.eqstorehash"></a>equivalence functors/storing hash values/hash</h6></div></div></div><p><codeclass="classname">cc_hash_table</code> and
fail at compilation, by design, if this is attempted.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="policy_interaction.sizeloadtrigger"></a>size/load-check trigger</h6></div></div></div><p>Assume a size policy issues an increasing sequence of sizes
respectively, then it is a good idea to have:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p>α<sub>max</sub> ~ 1 / q</p></li><liclass="listitem"><p>α<sub>min</sub>< 1 / (2 q)</p></li></ol></div><p>This will ensure that the amortized hash cost of each
α<sub>max</sub> is horrendous.</p></div></div></div></div><divclass="section"><divclass="titlepage"><div><div><h4class="title"><aid="pbds.design.container.tree"></a>tree</h4></div></div></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="container.tree.interface"></a>Interface</h5></div></div></div><p>The tree-based container has the following declaration:</p><preclass="programlisting">
</pre><p>The parameters have the following meaning:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p><codeclass="classname">Key</code> is the key type.</p></li><liclass="listitem"><p><codeclass="classname">Mapped</code> is the mapped-policy.</p></li><liclass="listitem"><p><codeclass="classname">Cmp_Fn</code> is a key comparison functor</p></li><liclass="listitem"><p><codeclass="classname">Tag</code> specifies which underlying data structure
exception and invalidation guarantees.</p></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="container.tree.details"></a>Details</h5></div></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.tree.node"></a>Node Invariants</h6></div></div></div><p>Consider the two trees in the graphic below, labels A and B. The first
these trees can support the usual queries: the first can easily
search for <codeclass="classname">0.4</code>; the second can easily search for
<codeclass="classname">std::make_pair(10, 41)</code>.</p><p>Each of these trees can efficiently support other queries.
The first can efficiently determine that the 2rd key in the
tree is <codeclass="constant">0.3</code>; the second can efficiently determine
whether any of its intervals overlaps
</p><preclass="programlisting">std::make_pair(29,42)</pre><p> (useful in geometric
applications or distributed file systems with leases, for
example). It should be noted that an <codeclass="classname">std::set</code> can
only solve these types of problems with linear complexity.</p><p>In order to do so, each tree stores some metadata in
each node, and maintains node invariants (see <aclass="xref"href="policy_data_structures.html#biblio.clrs2001"title="Introduction to Algorithms, 2nd edition">[biblio.clrs2001]</a>.) The first stores in
each node the size of the sub-tree rooted at the node; the
second stores at each node the maximal endpoint of the
intervals at the sub-tree rooted at the node.</p><divclass="figure"><aid="id-1.3.5.9.4.4.3.3.2.5"></a><pclass="title"><strong>Figure22.22.Tree node invariants</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_tree_node_invariants.png"align="middle"alt="Tree node invariants"/></div></div></div><brclass="figure-break"/><p>Supporting such trees is difficult for a number of
the second can support an <codeclass="classname">overlaps</code> method.</p></li></ol></div><divclass="figure"><aid="id-1.3.5.9.4.4.3.3.2.8"></a><pclass="title"><strong>Figure22.23.Tree node invalidation</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_tree_node_invalidations.png"align="middle"alt="Tree node invalidation"/></div></div></div><brclass="figure-break"/><p>These problems are solved by a combination of two means:
corresponding to a just-after-leaf node.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.tree.node.updator"></a>Node Updator</h6></div></div></div><p>The tree-based containers are parametrized by a
below).</p><divclass="figure"><aid="id-1.3.5.9.4.4.3.3.2.11.3"></a><pclass="title"><strong>Figure22.24.A tree and its update policy</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_tree_node_updator_policy_cd.png"align="middle"alt="A tree and its update policy"/></div></div></div><brclass="figure-break"/><p><codeclass="classname">node_update</code> (an instantiation of
nodes should have valid invariants, as in label B.</p><divclass="figure"><aid="id-1.3.5.9.4.4.3.3.2.11.8"></a><pclass="title"><strong>Figure22.25.Restoring node invariants</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_restoring_node_invariants.png"align="middle"alt="Restoring node invariants"/></div></div></div><brclass="figure-break"/><p>When a tree operation might invalidate some node invariant,
it invokes this method in its <codeclass="classname">node_update</code> base to
restore the invariant. For example, the graphic below shows
an <codeclass="function">insert</code> operation (point A); the tree performs some
operations, and calls the update functor three times (points B,
C, and D). (It is well known that any <codeclass="function">insert</code>,
<codeclass="function">erase</code>, <codeclass="function">split</code> or <codeclass="function">join</code>, can restore
all node invariants by a small number of node invariant updates (<aclass="xref"href="policy_data_structures.html#biblio.clrs2001"title="Introduction to Algorithms, 2nd edition">[biblio.clrs2001]</a>)
.</p><divclass="figure"><aid="id-1.3.5.9.4.4.3.3.2.11.10"></a><pclass="title"><strong>Figure22.26.Insert update sequence</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_update_seq_diagram.png"align="middle"alt="Insert update sequence"/></div></div></div><brclass="figure-break"/><p>To complete the description of the scheme, three questions
need to be answered:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p>How can a tree which supports order statistics define a
<codeclass="classname">node_update</code> are automatically methods of
the tree (<aclass="xref"href="policy_data_structures.html#biblio.alexandrescu01modern"title="Modern C++ Design: Generic Programming and Design Patterns Applied">[biblio.alexandrescu01modern]</a>).
to the following drawbacks:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p>Each node would carry a useless metadata object, wasting
invariants are irrelevant, and defines all accordingly.</p></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.tree.details.split"></a>Split and Join</h6></div></div></div><p>Tree-based containers support split and join methods.
tree and erasing from the source tree:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p>These methods are efficient - red-black trees are split
and the methods are exception-free. </p></li></ol></div></div></div></div><divclass="section"><divclass="titlepage"><div><div><h4class="title"><aid="pbds.design.container.trie"></a>Trie</h4></div></div></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="container.trie.interface"></a>Interface</h5></div></div></div><p>The trie-based container has the following declaration:</p><preclass="programlisting">
</pre><p>The parameters have the following meaning:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p><codeclass="classname">Key</code> is the key type.</p></li><liclass="listitem"><p><codeclass="classname">Mapped</code> is the mapped-policy.</p></li><liclass="listitem"><p><codeclass="classname">E_Access_Traits</code> is described in below.</p></li><liclass="listitem"><p><codeclass="classname">Tag</code> specifies which underlying data structure
to use, and is described shortly.</p></li><liclass="listitem"><p><codeclass="classname">Node_Update</code> is a policy for updating node
invariants. This is described below.</p></li><liclass="listitem"><p><codeclass="classname">Allocator</code> is an allocator
type.</p></li></ol></div><p>The <codeclass="classname">Tag</code> parameter specifies which underlying
data structure to use. Instantiating it by <codeclass="classname">pat_trie_tag</code>, specifies an
underlying PATRICIA trie (explained shortly); any other tag is
currently illegal.</p><p>Following is a description of a (PATRICIA) trie
(this implementation follows <aclass="xref"href="policy_data_structures.html#biblio.okasaki98mereable"title="Fast mergeable integer maps">[biblio.okasaki98mereable]</a> and
<aclass="xref"href="policy_data_structures.html#biblio.filliatre2000ptset"title="Ptset: Sets of integers implemented as Patricia trees">[biblio.filliatre2000ptset]</a>).
</p><p>A (PATRICIA) trie is similar to a tree, but with the
following differences:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p>It explicitly views keys as a sequence of elements.
characters; a trie can view a number as a sequence of
bits.</p></li><liclass="listitem"><p>It is not (necessarily) binary. Each node has fan-out n
+ 1, where n is the number of distinct
elements.</p></li><liclass="listitem"><p>It stores values only at leaf nodes.</p></li><liclass="listitem"><p>Internal nodes have the properties that A) each has at
least two children, and B) each shares the same prefix with
any of its descendant.</p></li></ol></div><p>A (PATRICIA) trie has some useful properties:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p>It can be configured to use large node fan-out, giving it
very efficient find performance (albeit at insertion
complexity and size).</p></li><liclass="listitem"><p>It works well for common-prefix keys.</p></li><liclass="listitem"><p>It can support efficiently queries such as which
keys match a certain prefix. This is sometimes useful in file
systems and routers, and for "type-ahead" aka predictive text matching
on mobile devices.</p></li></ol></div></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="container.trie.details"></a>Details</h5></div></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.trie.details.etraits"></a>Element Access Traits</h6></div></div></div><p>A trie inherently views its keys as sequences of elements.
accesses its keys' elements from the trie:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p>In some cases, the numerical value of an element is
<codeclass="varname">'s'</code>.</p><divclass="figure"><aid="id-1.3.5.9.4.4.4.3.2.10"></a><pclass="title"><strong>Figure22.28.A PATRICIA trie</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_pat_trie.png"align="middle"alt="A PATRICIA trie"/></div></div></div><brclass="figure-break"/></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.trie.details.node"></a>Node Invariants</h6></div></div></div><p>Trie-based containers support node invariants, as do
sharing the same node-updating policies:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p>A trie's <codeclass="classname">Node_Update</code> template-template
policies (which are explained below).</p><divclass="figure"><aid="id-1.3.5.9.4.4.4.3.3.5"></a><pclass="title"><strong>Figure22.29.A trie and its update policy</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_trie_node_updator_policy_cd.png"align="middle"alt="A trie and its update policy"/></div></div></div><brclass="figure-break"/><p>This library offers the following pre-defined trie node
is the null node updater.</p></li></ol></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.trie.details.split"></a>Split and Join</h6></div></div></div><p>Trie-based containers support split and join methods; the
these methods.</p></div></div></div><divclass="section"><divclass="titlepage"><div><div><h4class="title"><aid="pbds.design.container.list"></a>List</h4></div></div></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="container.list.interface"></a>Interface</h5></div></div></div><p>The list-based container has the following declaration:</p><preclass="programlisting">
<codeclass="classname">Key</code> is the key type.
</p></li><liclass="listitem"><p>
<codeclass="classname">Mapped</code> is the mapped-policy.
</p></li><liclass="listitem"><p>
<codeclass="classname">Eq_Fn</code> is a key equivalence functor.
</p></li><liclass="listitem"><p>
<codeclass="classname">Update_Policy</code> is a policy updating positions in
the list based on access patterns. It is described in the
following subsection.
</p></li><liclass="listitem"><p>
<codeclass="classname">Allocator</code> is an allocator type.
</p></li></ol></div><p>A list-based associative container is a container that
stores elements in a linked-list. It does not order the elements
by any particular order related to the keys. List-based
containers are primarily useful for creating "multimaps". In fact,
list-based containers are designed in this library expressly for
this purpose.</p><p>List-based containers might also be useful for some rare
cases, where a key is encapsulated to the extent that only
key-equivalence can be tested. Hash-based containers need to know
how to transform a key into a size type, and tree-based containers
need to know if some key is larger than another. List-based
associative containers, conversely, only need to know if two keys
are equivalent.</p><p>Since a list-based associative container does not order
elements by keys, is it possible to order the list in some
useful manner? Remarkably, many on-line competitive
algorithms exist for reordering lists to reflect access
prediction. (See <aclass="xref"href="policy_data_structures.html#biblio.motwani95random"title="Randomized Algorithms">[biblio.motwani95random]</a> and <aclass="xref"href="policy_data_structures.html#biblio.andrew04mtf"title="MTF, Bit, and COMB: A Guide to Deterministic and Randomized Algorithms for the List Update Problem">[biblio.andrew04mtf]</a>).
</p><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.list.details.ds"></a>Underlying Data Structure</h6></div></div></div><p>The graphic below shows a
faster.</p><divclass="figure"><aid="id-1.3.5.9.4.4.5.3.3.3"></a><pclass="title"><strong>Figure22.30.A simple list</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_simple_list.png"align="middle"alt="A simple list"/></div></div></div><brclass="figure-break"/><p>List-update algorithms reorder lists as elements are
which unconditionally move an accessed element to the front of
the list. The latter type is very useful in this library,
since there is no need to associate metadata with each element.
(See <aclass="xref"href="policy_data_structures.html#biblio.andrew04mtf"title="MTF, Bit, and COMB: A Guide to Deterministic and Randomized Algorithms for the List Update Problem">[biblio.andrew04mtf]</a>
</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.list.details.mapped"></a>Use in Multimaps</h6></div></div></div><p>In this library, there are no equivalents for the standard's
</p></li></ol></div></div></div></div><divclass="section"><divclass="titlepage"><div><div><h4class="title"><aid="pbds.design.container.priority_queue"></a>Priority Queue</h4></div></div></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="container.priority_queue.interface"></a>Interface</h5></div></div></div><p>The priority queue container has the following
</pre><p>The parameters have the following meaning:</p><divclass="orderedlist"><olclass="orderedlist"type="1"><liclass="listitem"><p><codeclass="classname">Value_Type</code> is the value type.</p></li><liclass="listitem"><p><codeclass="classname">Cmp_Fn</code> is a value comparison functor</p></li><liclass="listitem"><p><codeclass="classname">Tag</code> specifies which underlying data structure
an underlying pairing heap (<aclass="xref"href="policy_data_structures.html#biblio.fredman86pairing"title="The pairing heap: a new form of self-adjusting heap">[biblio.fredman86pairing]</a>),
binary heap (<aclass="xref"href="policy_data_structures.html#biblio.clrs2001"title="Introduction to Algorithms, 2nd edition">[biblio.clrs2001]</a>),
binomial heap (<aclass="xref"href="policy_data_structures.html#biblio.clrs2001"title="Introduction to Algorithms, 2nd edition">[biblio.clrs2001]</a>),
a binomial heap with a redundant binary counter (<aclass="xref"href="policy_data_structures.html#biblio.maverik_lowerbounds"title="Deamortization - Part 2: Binomial Heaps">[biblio.maverik_lowerbounds]</a>),
or a thin heap (<aclass="xref"href="policy_data_structures.html#biblio.kt99fat_heaps"title="New Heap Data Structures">[biblio.kt99fat_heaps]</a>).
</p><p>
As mentioned in the tutorial,
<codeclass="classname">__gnu_pbds::priority_queue</code> shares most of the
same interface with <codeclass="classname">std::priority_queue</code>.
E.g. if <codeclass="varname">q</code> is a priority queue of type
<codeclass="classname">Q</code>, then <codeclass="function">q.top()</code> will
return the "largest" value in the container (according to
different implementations.</p></div><divclass="section"><divclass="titlepage"><div><div><h5class="title"><aid="container.priority_queue.details"></a>Details</h5></div></div></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.priority_queue.details.iterators"></a>Iterators</h6></div></div></div><p>There are many different underlying-data structures for
simultaneously in many priority queues.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.priority_queue.details.d"></a>Underlying Data Structure</h6></div></div></div><p>There are three main implementations of priority queues: the
shown in the graphic below, in labels A1 and A2, label B, and label C.</p><divclass="figure"><aid="id-1.3.5.9.4.4.6.3.3.3"></a><pclass="title"><strong>Figure22.32.Underlying Priority-Queue Data-Structures.</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_priority_queue_different_underlying_dss.png"align="middle"alt="Underlying Priority-Queue Data-Structures."/></div></div></div><brclass="figure-break"/><p>Roughly speaking, any value that is both pushed and popped
from a priority queue must incur a logarithmic expense (in the
amortized sense). Any priority queue implementation that would
avoid this, would violate known bounds on comparison-based
sorting (see <aclass="xref"href="policy_data_structures.html#biblio.clrs2001"title="Introduction to Algorithms, 2nd edition">[biblio.clrs2001]</a> and <aclass="xref"href="policy_data_structures.html#biblio.brodal96priority"title="Worst-case efficient priority queues">[biblio.brodal96priority]</a>).
</p><p>Most implementations do
not differ in the asymptotic amortized complexity of
<codeclass="function">push</code> and <codeclass="function">pop</code> operations, but they differ in
the constants involved, in the complexity of other operations
(e.g., <codeclass="function">modify</code>), and in the worst-case
complexity of single operations. In general, the more
"structured" an implementation (i.e., the more internal
invariants it possesses) - the higher its amortized complexity
of <codeclass="function">push</code> and <codeclass="function">pop</code> operations.</p><p>This library implements different algorithms using a
single class: <codeclass="classname">priority_queue</code>.
Instantiating the <codeclass="classname">Tag</code> template parameter, "selects"
performance.</p></div><divclass="section"><divclass="titlepage"><div><div><h6class="title"><aid="container.priority_queue.details.traits"></a>Traits</h6></div></div></div><p>It would be nice if all priority queues could
</p><divclass="figure"><aid="id-1.3.5.9.4.4.6.3.4.4"></a><pclass="title"><strong>Figure22.33.Priority-Queue Data-Structure Tags.</strong></p><divclass="figure-contents"><divclass="mediaobject"align="center"><imgsrc="../images/pbds_priority_queue_tag_hierarchy.png"align="middle"alt="Priority-Queue Data-Structure Tags."/></div></div></div><brclass="figure-break"/><p>Additionally, a traits mechanism can be used to query a
to get the invalidation guarantee type of a priority queue.</p><p>It is easy to understand from the graphic above, what <codeclass="classname">container_traits<Cntnr>::invalidation_guarantee</code>
will be for different implementations. All implementations of
type represented by label B have <codeclass="classname">point_invalidation_guarantee</code>:
the container can freely internally reorganize the nodes -
range-type iterators are invalidated, but point-type iterators
are always valid. Implementations of type represented by labels A1 and A2 have <codeclass="classname">basic_invalidation_guarantee</code>:
the container can freely internally reallocate the array - both
point-type and range-type iterators might be invalidated.</p><p>
This has major implications, and constitutes a good reason to avoid
using binary heaps. A binary heap can perform <codeclass="function">modify</code>
or <codeclass="function">erase</code> efficiently given a valid point-type
iterator. However, in order to supply it with a valid point-type
iterator, one needs to iterate (linearly) over all
values, then supply the relevant iterator (recall that a
range-type iterator can always be converted to a point-type
iterator). This means that if the number of <codeclass="function">modify</code> or
<codeclass="function">erase</code> operations is non-negligible (say
super-logarithmic in the total sequence of operations) - binary