<!--
    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>make_heap()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="lower-bound.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="map-h.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>make_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 creates a heap</P>
<A NAME="sec3"><H3>Synopsis</H3></A>

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

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

  template &lt;class RandomAccessIterator, class Compare&gt;
  void
  make_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>
<UL>
<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><A HREF="pop-heap.html">pop_heap()</A></SAMP> algorithm, or a new element can be added by the <SAMP><A HREF="push-heap.html">push_heap()</A></SAMP> algorithm, in <SAMP>O(log (N))</SAMP> time.</P></LI>
</UL>
<P>These properties make heaps useful as priority queues.</P>
<P>The heap algorithms use <SAMP>operator&lt;()</SAMP> as the default comparison. In all of the algorithms, an alternate binary predicate function object can be specified.</P>
<P>The first version of the <SAMP>make_heap()</SAMP> algorithm arranges the elements in the range <SAMP>[start, finish)</SAMP> into a heap using <SAMP>operator&lt;()</SAMP> to perform comparisons. The second version uses the comparison function object <SAMP>comp</SAMP>. Since the only requirements for a heap are the two listed above, <SAMP>make_heap()</SAMP> is not required to do anything within the range <SAMP>(start, finish - 1)</SAMP>. </P>
<A NAME="sec5"><H3>Complexity</H3></A>
<P>This algorithm makes at most <SAMP>3 * (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="pop-heap.html">pop_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++, 25.3.6.3</I></P>

<BR>
<HR>
<A HREF="lower-bound.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="map-h.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>
