libstdc++
thin_heap_/erase_fn_imps.hpp
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2005, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the terms
00007 // of the GNU General Public License as published by the Free Software
00008 // Foundation; either version 3, or (at your option) any later
00009 // version.
00010 
00011 // This library is distributed in the hope that it will be useful, but
00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
00026 
00027 // Permission to use, copy, modify, sell, and distribute this software
00028 // is hereby granted without fee, provided that the above copyright
00029 // notice appears in all copies, and that both that copyright notice
00030 // and this permission notice appear in supporting documentation. None
00031 // of the above authors, nor IBM Haifa Research Laboratories, make any
00032 // representation about the suitability of this software for any
00033 // purpose. It is provided "as is" without express or implied
00034 // warranty.
00035 
00036 /**
00037  * @file thin_heap_/erase_fn_imps.hpp
00038  * Contains an implementation for thin_heap_.
00039  */
00040 
00041 PB_DS_CLASS_T_DEC
00042 void
00043 PB_DS_CLASS_C_DEC::
00044 pop()
00045 {
00046   PB_DS_ASSERT_VALID((*this))
00047   _GLIBCXX_DEBUG_ASSERT(!base_type::empty());
00048   _GLIBCXX_DEBUG_ASSERT(m_p_max != 0);
00049 
00050   node_pointer p_nd = m_p_max;
00051   remove_max_node();
00052   base_type::actual_erase_node(p_nd);
00053   PB_DS_ASSERT_VALID((*this))
00054 }
00055 
00056 PB_DS_CLASS_T_DEC
00057 inline void
00058 PB_DS_CLASS_C_DEC::
00059 remove_max_node()
00060 {
00061   to_aux_except_max();
00062   make_from_aux();
00063 }
00064 
00065 PB_DS_CLASS_T_DEC
00066 void
00067 PB_DS_CLASS_C_DEC::
00068 to_aux_except_max()
00069 {
00070   node_pointer p_add = base_type::m_p_root;
00071   while (p_add != m_p_max)
00072     {
00073       node_pointer p_next_add = p_add->m_p_next_sibling;
00074       add_to_aux(p_add);
00075       p_add = p_next_add;
00076     }
00077 
00078   p_add = m_p_max->m_p_l_child;
00079   while (p_add != 0)
00080     {
00081       node_pointer p_next_add = p_add->m_p_next_sibling;
00082       p_add->m_metadata = p_add->m_p_l_child == 0 ?
00083     0 : p_add->m_p_l_child->m_metadata + 1;
00084 
00085       add_to_aux(p_add);
00086       p_add = p_next_add;
00087     }
00088 
00089   p_add = m_p_max->m_p_next_sibling;
00090   while (p_add != 0)
00091     {
00092       node_pointer p_next_add = p_add->m_p_next_sibling;
00093       add_to_aux(p_add);
00094       p_add = p_next_add;
00095     }
00096 }
00097 
00098 PB_DS_CLASS_T_DEC
00099 inline void
00100 PB_DS_CLASS_C_DEC::
00101 add_to_aux(node_pointer p_nd)
00102 {
00103   size_type r = p_nd->m_metadata;
00104   while (m_a_aux[r] != 0)
00105     {
00106       _GLIBCXX_DEBUG_ASSERT(p_nd->m_metadata < rank_bound());
00107       if (Cmp_Fn::operator()(m_a_aux[r]->m_value, p_nd->m_value))
00108     make_child_of(m_a_aux[r], p_nd);
00109       else
00110     {
00111       make_child_of(p_nd, m_a_aux[r]);
00112       p_nd = m_a_aux[r];
00113     }
00114 
00115       m_a_aux[r] = 0;
00116       ++r;
00117     }
00118 
00119   _GLIBCXX_DEBUG_ASSERT(p_nd->m_metadata < rank_bound());
00120 
00121   m_a_aux[r] = p_nd;
00122 }
00123 
00124 PB_DS_CLASS_T_DEC
00125 inline void
00126 PB_DS_CLASS_C_DEC::
00127 make_child_of(node_pointer p_nd, node_pointer p_new_parent)
00128 {
00129   _GLIBCXX_DEBUG_ASSERT(p_nd->m_metadata == p_new_parent->m_metadata);
00130   _GLIBCXX_DEBUG_ASSERT(m_a_aux[p_nd->m_metadata] == p_nd ||
00131            m_a_aux[p_nd->m_metadata] == p_new_parent);
00132 
00133   ++p_new_parent->m_metadata;
00134   base_type::make_child_of(p_nd, p_new_parent);
00135 }
00136 
00137 PB_DS_CLASS_T_DEC
00138 inline void
00139 PB_DS_CLASS_C_DEC::
00140 make_from_aux()
00141 {
00142   base_type::m_p_root = m_p_max = 0;
00143   const size_type rnk_bnd = rank_bound();
00144   size_type i = 0;
00145   while (i < rnk_bnd)
00146     {
00147       if (m_a_aux[i] != 0)
00148     {
00149       make_root_and_link(m_a_aux[i]);
00150       m_a_aux[i] = 0;
00151     }
00152       ++i;
00153     }
00154 
00155   PB_DS_ASSERT_AUX_NULL((*this))
00156 }
00157 
00158 PB_DS_CLASS_T_DEC
00159 inline void
00160 PB_DS_CLASS_C_DEC::
00161 remove_node(node_pointer p_nd)
00162 {
00163   node_pointer p_parent = p_nd;
00164   while (base_type::parent(p_parent) != 0)
00165     p_parent = base_type::parent(p_parent);
00166 
00167   base_type::bubble_to_top(p_nd);
00168   m_p_max = p_nd;
00169 
00170   node_pointer p_fix = base_type::m_p_root;
00171   while (p_fix != 0&&  p_fix->m_p_next_sibling != p_parent)
00172     p_fix = p_fix->m_p_next_sibling;
00173 
00174   if (p_fix != 0)
00175     p_fix->m_p_next_sibling = p_nd;
00176 
00177   remove_max_node();
00178 }
00179 
00180 PB_DS_CLASS_T_DEC
00181 inline void
00182 PB_DS_CLASS_C_DEC::
00183 clear()
00184 {
00185   base_type::clear();
00186   m_p_max = 0;
00187 }
00188 
00189 PB_DS_CLASS_T_DEC
00190 void
00191 PB_DS_CLASS_C_DEC::
00192 erase(point_iterator it)
00193 {
00194   PB_DS_ASSERT_VALID((*this))
00195   _GLIBCXX_DEBUG_ASSERT(!base_type::empty());
00196 
00197   node_pointer p_nd = it.m_p_nd;
00198   remove_node(p_nd);
00199   base_type::actual_erase_node(p_nd);
00200   PB_DS_ASSERT_VALID((*this))
00201 }
00202 
00203 PB_DS_CLASS_T_DEC
00204 template<typename Pred>
00205 typename PB_DS_CLASS_C_DEC::size_type
00206 PB_DS_CLASS_C_DEC::
00207 erase_if(Pred pred)
00208 {
00209   PB_DS_ASSERT_VALID((*this))
00210   if (base_type::empty())
00211     {
00212       PB_DS_ASSERT_VALID((*this))
00213       return 0;
00214     }
00215 
00216   base_type::to_linked_list();
00217   node_pointer p_out = base_type::prune(pred);
00218   size_type ersd = 0;
00219   while (p_out != 0)
00220     {
00221       ++ersd;
00222       node_pointer p_next = p_out->m_p_next_sibling;
00223       base_type::actual_erase_node(p_out);
00224       p_out = p_next;
00225     }
00226 
00227   node_pointer p_cur = base_type::m_p_root;
00228   m_p_max = base_type::m_p_root = 0;
00229   while (p_cur != 0)
00230     {
00231       node_pointer p_next = p_cur->m_p_next_sibling;
00232       make_root_and_link(p_cur);
00233       p_cur = p_next;
00234     }
00235 
00236   PB_DS_ASSERT_VALID((*this))
00237   return ersd;
00238 }
00239 
00240 PB_DS_CLASS_T_DEC
00241 inline typename PB_DS_CLASS_C_DEC::size_type
00242 PB_DS_CLASS_C_DEC::
00243 rank_bound()
00244 {
00245   using namespace std;
00246   const size_t* const p_upper =
00247     std::upper_bound(g_a_rank_bounds,
00248              g_a_rank_bounds + num_distinct_rank_bounds,
00249              base_type::m_size);
00250 
00251   if (p_upper == g_a_rank_bounds + num_distinct_rank_bounds)
00252     return max_rank;
00253 
00254   return (p_upper - g_a_rank_bounds);
00255 }