<!--
    Licensed to the Apache Software  Foundation (ASF) under one or more
    contributor  license agreements.  See  the NOTICE  file distributed
    with  this  work  for  additional information  regarding  copyright
    ownership.   The ASF  licenses this  file to  you under  the Apache
    License, Version  2.0 (the  License); you may  not use  this file
    except in  compliance with the License.   You may obtain  a copy of
    the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the  License is distributed on an  "AS IS" BASIS,
    WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
    implied.   See  the License  for  the  specific language  governing
    permissions and limitations under the License.

    Copyright 1999-2007 Rogue Wave Software, Inc.
-->

<HTML>
<HEAD>
<TITLE>pop_heap()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="pointer-to-unary-function.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="predicates.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Apache C++ Standard Library Reference Guide</B></DIV>
<H2>pop_heap()</H2>
<P><B>Library:</B>&nbsp;&nbsp;<A HREF="2-9.html">Algorithms</A></P>

<PRE><HR><B><I>Function</I></B><HR></PRE>

<UL>
<LI><A HREF="#sec1">Local Index</A></LI>
<LI><A HREF="#sec2">Summary</A></LI>
<LI><A HREF="#sec3">Synopsis</A></LI>
<LI><A HREF="#sec4">Description</A></LI>
<LI><A HREF="#sec5">Complexity</A></LI>
<LI><A HREF="#sec6">Example</A></LI>
<LI><A HREF="#sec7">See Also</A></LI>
<LI><A HREF="#sec8">Standards Conformance</A></LI>
</UL>
<A NAME="sec1"><H3>Local Index</H3></A>
No Entries
<A NAME="sec2"><H3>Summary</H3></A>
<P>Algorithm that moves the largest element off the heap</P>
<A NAME="sec3"><H3>Synopsis</H3></A>

<PRE>#include &lt;algorithm&gt;

namespace std {
template &lt;class RandomAccessIterator&gt;
  void
  pop_heap(RandomAccessIterator start,
           RandomAccessIterator finish);

template &lt;class RandomAccessIterator, class Compare&gt;
  void
  pop_heap(RandomAccessIterator start,
           RandomAccessIterator finish, Compare comp);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>A heap is a particular organization of elements in a range between two random access iterators <SAMP>[a, b)</SAMP>. Its two key properties are:</P>
<OL>
<LI><P CLASS="LIST"><SAMP>*a</SAMP> is the largest element in the range.</P></LI>
<LI><P CLASS="LIST"><SAMP>*a</SAMP> may be removed by the <SAMP>pop_heap()</SAMP> algorithm or a new element may be added by the <SAMP>pop_heap()</SAMP> algorithm, in <SAMP>O(log(N))</SAMP> time.</P></LI>
</OL>
<P>These properties make heaps useful as priority queues.</P>
<P>The <SAMP>pop_heap()</SAMP> algorithm uses <SAMP>operator&lt;()</SAMP> as the default comparison. An alternate comparison operator can be specified to the second overload of the function template.</P>
<P>The <SAMP>pop_heap()</SAMP> algorithm can be used as part of an operation to remove the largest element from a heap. It assumes that the range <SAMP>[start, finish)</SAMP> is a valid heap (in other words, that <SAMP>start</SAMP> is the largest element in the heap or the first element based on the alternate comparison operator). It then swaps the value in the location <SAMP>start</SAMP> with the value in the location <SAMP>finish - 1</SAMP> and makes the range <SAMP>[start, finish - 1)</SAMP> back into a heap.</P>
<A NAME="sec5"><H3>Complexity</H3></A>
<P><SAMP>pop_heap()</SAMP> performs at most <SAMP>2 * log(finish - start)</SAMP> comparisons.</P>
<A NAME="sec6"><H3>Example</H3></A>

<UL><PRE>//
//  heap_ops.cpp
//

#include &lt;algorithm&gt;    // for copy, make_heap, pop_heap, 
                        // and push_heap
#include &lt;functional&gt;   // for less
#include &lt;iostream&gt;     // for cout
#include &lt;iterator&gt;     // for ostream_iterator
#include &lt;vector&gt;       // for vector



template &lt;class charT, class Traits, class T, class Allocator&gt;
void print_vector (std::basic_ostream&lt;charT, Traits&gt; &amp;strm,
                   const std::vector&lt;T, Allocator&gt;   &amp;v)
{
    std::copy (v.begin (), v.end (),
               std::ostream_iterator&lt;T, charT, Traits&gt; 
                                    (strm, " "));

    strm &lt;&lt; std::endl;
}


int main ()
{
    typedef std::vector&lt;int, std::allocator&lt;int&gt; &gt; Vector;

    const Vector::value_type d1[] = { 1, 2, 3, 4 };
    const Vector::value_type d2[] = { 1, 3, 2, 4 };

    // Set up two vectors.
    Vector v1 (d1 + 0, d1 + sizeof d1 / sizeof *d1);
    Vector v2 (d2 + 0, d2 + sizeof d2 / sizeof *d2);

    // Make heaps.
    std::make_heap (v1.begin (), v1.end ());
    std::make_heap (v2.begin (), v2.end (), std::less&lt;int&gt;());

    // v1 = (4, x, y, z)  and  v2 = (4, x, y, z)

    // Note that x, y and z represent the remaining values 
    // in the container (other than 4).  The definition of 
    // the heap and heap operations does not require any 
    // particular ordering of these values.

    // Copy both vectors to cout.
    print_vector (std::cout, v1);
    print_vector (std::cout, v2);

    // Now let's pop.
    std::pop_heap (v1.begin (), v1.end ());
    std::pop_heap (v2.begin (), v2.end (), std::less&lt;int&gt;());

    print_vector (std::cout, v1);
    print_vector (std::cout, v2);

    // And push.
    std::push_heap (v1.begin (), v1.end ());
    std::push_heap (v2.begin (), v2.end (), std::less&lt;int&gt;());

    print_vector (std::cout, v1);
    print_vector (std::cout, v2);

    // Now sort those heaps.
    std::sort_heap (v1.begin (), v1.end ());
    std::sort_heap (v2.begin (), v2.end (), std::less&lt;int&gt;());

    print_vector (std::cout, v1);
    print_vector (std::cout, v2);

    return 0;
}


Program Output:
</PRE></UL>
<UL><PRE>4 2 3 1 
4 3 2 1 
3 2 1 4 
3 1 2 4 
4 3 1 2 
4 3 2 1 
1 2 3 4 
1 2 3 4 
</PRE></UL>
<A NAME="sec7"><H3>See Also</H3></A>
<P><SAMP><A HREF="make-heap.html">make_heap()</A></SAMP>,  <SAMP><A HREF="push-heap.html">push_heap()</A></SAMP>,  <SAMP><A HREF="sort-heap.html">sort_heap()</A></SAMP></P>
<A NAME="sec8"><H3>Standards Conformance</H3></A>
<P><I>ISO/IEC 14882:1998 -- International Standard for Information Systems -- Programming Language C++, Section 25.3.6.2</I></P>

<BR>
<HR>
<A HREF="pointer-to-unary-function.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="predicates.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A>

<!-- Google Analytics tracking code -->
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
    _uacct = "UA-1775151-1";
    urchinTracker();
</script>
<!-- end of Google Analytics tracking code -->

</BODY>
</HTML>
