<!--
    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>partial_sort()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="pair.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="partial-sort-copy.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>partial_sort()</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>A generic algorithm for sorting collections of entities</P>
<A NAME="sec3"><H3>Synopsis</H3></A>

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

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

  template &lt;class RandomAccessIterator, class Compare&gt;
  void partial_sort(RandomAccessIterator start,
                    RandomAccessIterator mid, 
                    RandomAccessIterator finish, 
                    Compare comp);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>The <SAMP>partial_sort()</SAMP> algorithm takes the range <SAMP>[start,finish)</SAMP> and sorts the first <SAMP>mid - start</SAMP> values in ascending order. The remaining elements in the range (those in <SAMP>[mid, finish)</SAMP>) are not in any defined order. The first version of the algorithm uses <SAMP>operator&lt;()</SAMP> as the comparison operator for the sort. The second version uses the function object <SAMP>comp</SAMP>.</P>
<A NAME="sec5"><H3>Complexity</H3></A>
<P><SAMP>partial_sort()</SAMP> does approximately<SAMP> (finish  - start) * log(mid-start) </SAMP>comparisons. This implementation of <SAMP>partial_sort()</SAMP> is implemented using heapsort, which is <SAMP>O(N * log(N))</SAMP> in the worst case. </P>
<A NAME="sec6"><H3>Example</H3></A>

<UL><PRE>//
//  partsort.cpp
//

#include &lt;algorithm&gt;   // for partial_sort
#include &lt;iostream&gt;    // for cout, endl
#include &lt;iterator&gt;    // for ostream_iterator
#include &lt;vector&gt;      // for vector



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

    typedef std::ostream_iterator&lt;int, char, 
                                  std::char_traits&lt;char&gt; &gt;
            Iter;

    const Vector::value_type a[] = {
        17, 3,  5,  -4, 1, 12, -10, -1, 14, 7,
        -6, 8, 15, -11, 2, -2,  18,  4, -3, 0
    };

    Vector v1 (a + 0, a + sizeof a / sizeof *a);

    // Output original vector.
    std::cout &lt;&lt; "For the vector: ";
    std::copy (v1.begin (), v1.end (), Iter (std::cout, " "));

    // Partial sort the first seven elements.
    std::partial_sort (v1.begin (), v1.begin () + 7, 
                       v1.end ());

    // Output result.
    std::cout &lt;&lt; "\n\nA partial_sort of seven elements "
              &lt;&lt; "gives: \n     ";
    std::copy (v1.begin (), v1.end (), Iter (std::cout, " "));
    std::cout &lt;&lt; std::endl;

    // A vector of ten elements.
    Vector v2 (Vector::size_type (10), 0);

    // Sort the last ten elements in v1 into v2.
    std::partial_sort_copy (v1.begin () + 10, v1.end (),
                            v2.begin (), v2.end ());

    // Output result.
    std::cout
        &lt;&lt; "\nA partial_sort_copy of the last ten elements "
        &lt;&lt; "gives: \n     ";
    std::copy (v2.begin (), v2.end (), Iter (std::cout, " "));

    std::cout &lt;&lt; std::endl;

    return 0;
}


Program Output:
</PRE></UL>
<UL><PRE>For the vector: 17 3 5 -4 1 12 -10 -1 14 7 -6 8 15 -11 2 -2 
18 4 -3 0 

A partial_sort of seven elements gives: 
     -11 -10 -6 -4 -3 -2 -1 17 14 12 7 8 15 5 3 2 18 4 1 0 

A partial_sort_copy of the last ten elements gives: 
     0 1 2 3 4 5 7 8 15 18 
</PRE></UL>
<A NAME="sec7"><H3>See Also</H3></A>
<P><SAMP><A HREF="sort.html">sort()</A></SAMP>, <SAMP><A HREF="stable-sort.html">stable_sort()</A></SAMP>, <SAMP><A HREF="partial-sort-copy.html">partial_sort_copy()</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.1.3</I></P>

<BR>
<HR>
<A HREF="pair.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="partial-sort-copy.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>
