<!--
    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>stable_partition()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="sstream-h.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="stable-sort.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>stable_partition()</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>An algorithm that places all of the entities that satisfy the given predicate before all of the entities that do not, while maintaining the relative order of elements in each group</P>
<A NAME="sec3"><H3>Synopsis</H3></A>

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

namespace std {
  template &lt;class BidirectionalIterator, class Predicate&gt;
  BidirectionalIterator
  stable_partition(BidirectionalIterator start,
                   BidirectionalIterator finish,
                   Predicate pred);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>For the range <SAMP>[start, finish)</SAMP>, the <SAMP>stable_partition()</SAMP> algorithm places all elements that satisfy <SAMP>pred</SAMP> before all elements that do not satisfy it. It returns an iterator <SAMP>i</SAMP> that is one past the end of the group of elements that satisfies <SAMP>pred</SAMP>. The relative order of the elements in both groups is maintained. </P>
<P>The <SAMP><A HREF="partition.html">partition()</A></SAMP> algorithm can be used when it is not necessary to maintain the relative order of elements within the groups that do and do not match the predicate.</P>
<A NAME="sec5"><H3>Complexity</H3></A>
<P>The <SAMP>stable_partition()</SAMP> algorithm does at most <SAMP>(finish - start) * log(finish - start)</SAMP> swaps and applies the predicate exactly <SAMP>finish - start</SAMP> times. </P>
<A NAME="sec6"><H3>Example</H3></A>

<UL><PRE>//
//  prtition.cpp
//

#include &lt;algorithm&gt;    // for copy
#include &lt;deque&gt;        // for deque
#include &lt;functional&gt;   // for unary_function
#include &lt;iostream&gt;     // for cout, endl
#include &lt;iterator&gt;     // for ostream_iterator



// Create a new predicate from unary_function.
template &lt;class Arg&gt;
struct is_even : public std::unary_function&lt;Arg, bool&gt;
{
    bool operator()(const Arg &amp;arg1) const {
        return (arg1 % 2) == 0;
    } 
};

int main ()
{
    typedef std::deque&lt;int, std::allocator&lt;int&gt; &gt; Deque;
    typedef std::ostream_iterator&lt;int, char,
                                  std::char_traits&lt;char&gt; &gt;
            Iter;

    // Initialize a deque with an array of integers.
    const Deque::value_type a[] = { 1, 2, 3, 4, 5,
                                    6, 7, 8, 9, 10 };

    Deque d1 (a + 0, a + sizeof a / sizeof *a);
    Deque d2 (d1);

    // Print out the original values.
    std::cout &lt;&lt; "Unpartitioned values: \t\t";
    std::copy (d1.begin (), d1.end (), Iter (std::cout, " "));

    // A partition of the deque according to even/oddness.
    std::partition (d2.begin (), d2.end (), is_even&lt;int&gt;());

    // Output result of partition.
    std::cout &lt;&lt; "\nPartitioned values: \t\t";
    std::copy (d2.begin (), d2.end (), Iter (std::cout, " "));

    // A stable partition of the deque according to 
    // even/oddness.
    std::stable_partition (d1.begin (), d1.end (),
                           is_even&lt;int&gt;());

    // Output result of partition.
    std::cout &lt;&lt; "\nStable partitioned values: \t";
    std::copy (d1.begin (), d1.end (), Iter (std::cout, " "));
    std::cout &lt;&lt; std::endl;

    return 0;
}


Program Files:
</PRE></UL>
<UL><PRE>Unpartitioned values:     1 2 3 4 5 6 7 8 9 10 
Partitioned values:     10 2 8 4 6 5 7 3 9 1 
Stable partitioned values:   2 4 6 8 10 1 3 5 7 9 
</PRE></UL>
<A NAME="sec7"><H3>See Also</H3></A>
<P><SAMP><A HREF="partition.html">partition()</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.2.12</I></P>

<BR>
<HR>
<A HREF="sstream-h.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="stable-sort.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>
