libstdc++
binary_heap_/insert_fn_imps.hpp
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2005, 2006, 2009, 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 binary_heap_/insert_fn_imps.hpp
00038  * Contains an implementation class for a binary_heap.
00039  */
00040 
00041 PB_DS_CLASS_T_DEC
00042 inline typename PB_DS_CLASS_C_DEC::point_iterator
00043 PB_DS_CLASS_C_DEC::
00044 push(const_reference r_val)
00045 {
00046   PB_DS_ASSERT_VALID((*this))
00047   insert_value(r_val, s_no_throw_copies_ind);
00048   push_heap();
00049   PB_DS_ASSERT_VALID((*this))
00050   return point_iterator(m_a_entries);
00051 }
00052 
00053 PB_DS_CLASS_T_DEC
00054 inline void
00055 PB_DS_CLASS_C_DEC::
00056 insert_value(value_type val, true_type)
00057 {
00058   resize_for_insert_if_needed();
00059   m_a_entries[m_size++] = val;
00060 }
00061 
00062 PB_DS_CLASS_T_DEC
00063 inline void
00064 PB_DS_CLASS_C_DEC::
00065 insert_value(const_reference r_val, false_type)
00066 {
00067   resize_for_insert_if_needed();
00068   pointer p_new = s_value_allocator.allocate(1);
00069   cond_dealtor_t cond(p_new);
00070   new (p_new) value_type(r_val);
00071   cond.set_no_action();
00072   m_a_entries[m_size++] = p_new;
00073 }
00074 
00075 PB_DS_CLASS_T_DEC
00076 inline void
00077 PB_DS_CLASS_C_DEC::
00078 resize_for_insert_if_needed()
00079 {
00080   if (!resize_policy::resize_needed_for_grow(m_size))
00081     {
00082       _GLIBCXX_DEBUG_ASSERT(m_size < m_actual_size);
00083       return;
00084     }
00085 
00086   const size_type new_size = resize_policy::get_new_size_for_grow();
00087   entry_pointer new_entries = s_entry_allocator.allocate(new_size);
00088   resize_policy::notify_grow_resize();
00089 
00090   std::copy(m_a_entries, m_a_entries + m_size, new_entries);
00091   s_entry_allocator.deallocate(m_a_entries, m_actual_size);
00092   m_actual_size = new_size;
00093   m_a_entries = new_entries;
00094   make_heap();
00095 }
00096 
00097 PB_DS_CLASS_T_DEC
00098 void
00099 PB_DS_CLASS_C_DEC::
00100 modify(point_iterator it, const_reference r_new_val)
00101 {
00102   PB_DS_ASSERT_VALID((*this))
00103   swap_value_imp(it.m_p_e, r_new_val, s_no_throw_copies_ind);
00104   fix(it.m_p_e);
00105   PB_DS_ASSERT_VALID((*this))
00106   _GLIBCXX_DEBUG_ASSERT(is_heap());
00107 }
00108 
00109 PB_DS_CLASS_T_DEC
00110 void
00111 PB_DS_CLASS_C_DEC::
00112 fix(entry_pointer p_e)
00113 {
00114   size_type i = p_e - m_a_entries;
00115   if (i > 0 && entry_cmp::operator()(m_a_entries[parent(i)], m_a_entries[i]))
00116     {
00117       size_type parent_i = parent(i);
00118       while (i > 0
00119          && entry_cmp::operator()(m_a_entries[parent_i], m_a_entries[i]))
00120     {
00121       std::swap(m_a_entries[i], m_a_entries[parent_i]);
00122       i = parent_i;
00123       parent_i = parent(i);
00124     }
00125 
00126       PB_DS_ASSERT_VALID((*this))
00127       return;
00128     }
00129 
00130   while (i < m_size)
00131     {
00132       const size_type lchild_i = left_child(i);
00133       const size_type rchild_i = right_child(i);
00134       _GLIBCXX_DEBUG_ASSERT(rchild_i > lchild_i);
00135 
00136       const bool smaller_than_lchild = lchild_i < m_size &&
00137     entry_cmp::operator()(m_a_entries[i], m_a_entries[lchild_i]);
00138 
00139       const bool smaller_than_rchild = rchild_i < m_size &&
00140     entry_cmp::operator()(m_a_entries[i], m_a_entries[rchild_i]);
00141 
00142       const bool swap_with_rchild = smaller_than_rchild && (!smaller_than_lchild || entry_cmp::operator()(m_a_entries[lchild_i], m_a_entries[rchild_i]));
00143 
00144       const bool swap_with_lchild = !swap_with_rchild && smaller_than_lchild;
00145 
00146       if (swap_with_lchild)
00147     {
00148       std::swap(m_a_entries[i], m_a_entries[lchild_i]);
00149       i = lchild_i;
00150     }
00151       else if (swap_with_rchild)
00152     {
00153       std::swap(m_a_entries[i], m_a_entries[rchild_i]);
00154       i = rchild_i;
00155     }
00156       else
00157     i = m_size;
00158     }
00159 }
00160 
00161 PB_DS_CLASS_T_DEC
00162 inline void
00163 PB_DS_CLASS_C_DEC::
00164 swap_value_imp(entry_pointer p_e, value_type new_val, true_type)
00165 { *p_e = new_val; }
00166 
00167 PB_DS_CLASS_T_DEC
00168 inline void
00169 PB_DS_CLASS_C_DEC::
00170 swap_value_imp(entry_pointer p_e, const_reference r_new_val, false_type)
00171 {
00172   value_type tmp(r_new_val);
00173   (*p_e)->swap(tmp);
00174 }