⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adjacency_list.hpp

📁 C++的一个好库。。。现在很流行
💻 HPP
📖 第 1 页 / 共 5 页
字号:
  template <class Tag, class Vertex, class Iter, class Property>
  const typename property_value<Property,Tag>::type&
  get(Tag property_tag,
      const detail::stored_edge_iter<Vertex, Iter, Property>& e)
  {
    return get_property_value(e.get_property(), property_tag);
  }

  template <class Tag, class Vertex, class EdgeVec, class Property>
  const typename property_value<Property,Tag>::type&
  get(Tag property_tag,
      const detail::stored_ra_edge_iter<Vertex, EdgeVec, Property>& e)
  {
    return get_property_value(e.get_property(), property_tag);
  }
    
    //=========================================================================
    // Directed Edges Helper Class

    namespace detail {

      // O(E/V)
      template <class edge_descriptor, class EdgeList, class StoredProperty>
      inline void
      remove_directed_edge_dispatch(edge_descriptor, EdgeList& el,
                                    StoredProperty& p)
      {
        for (typename EdgeList::iterator i = el.begin();
             i != el.end(); ++i)
          if (&(*i).get_property() == &p) {
            el.erase(i);
            return;
          }
      }

      template <class incidence_iterator, class EdgeList, class Predicate>
      inline void
      remove_directed_edge_if_dispatch(incidence_iterator first,
                                       incidence_iterator last, 
                                       EdgeList& el, Predicate pred,
                                       boost::allow_parallel_edge_tag)
      {
        // remove_if
        while (first != last && !pred(*first))
          ++first;
        incidence_iterator i = first;
        if (first != last)
          for (; i != last; ++i)
            if (!pred(*i)) {
              *first.base() = *i.base();
              ++first;
            }
        el.erase(first.base(), el.end());
      }
      template <class incidence_iterator, class EdgeList, class Predicate>
      inline void
      remove_directed_edge_if_dispatch(incidence_iterator first,
                                       incidence_iterator last, 
                                       EdgeList& el, 
                                       Predicate pred,
                                       boost::disallow_parallel_edge_tag)
      {
        for (incidence_iterator next = first;
             first != last; first = next) {
          ++next;
          if (pred(*first))
            el.erase( first.base() );
        }
      }

      template <class PropT, class Graph, class incidence_iterator, 
                class EdgeList, class Predicate>
      inline void
      undirected_remove_out_edge_if_dispatch(Graph& g, 
                                             incidence_iterator first,
                                             incidence_iterator last, 
                                             EdgeList& el, Predicate pred,
                                             boost::allow_parallel_edge_tag)
      {
        // remove_if
        while (first != last && !pred(*first))
          ++first;
        incidence_iterator i = first;
        bool self_loop_removed = false;
        if (first != last)
          for (; i != last; ++i) {
            if (self_loop_removed) {
              /* With self loops, the descriptor will show up
               * twice. The first time it will be removed, and now it
               * will be skipped.
               */
              self_loop_removed = false;
            }
            else if (!pred(*i)) {
              *first.base() = *i.base();
              ++first;
            } else {
              if (source(*i, g) == target(*i, g)) self_loop_removed = true;
              else {
                // Remove the edge from the target
                detail::remove_directed_edge_dispatch
                  (*i, 
                   g.out_edge_list(target(*i, g)), 
                   *(PropT*)(*i).get_property());
              }

              // Erase the edge property
              g.m_edges.erase( (*i.base()).get_iter() );
            }
          }
        el.erase(first.base(), el.end());
      }
      template <class PropT, class Graph, class incidence_iterator, 
                class EdgeList, class Predicate>
      inline void
      undirected_remove_out_edge_if_dispatch(Graph& g, 
                                             incidence_iterator first,
                                             incidence_iterator last, 
                                             EdgeList& el, 
                                             Predicate pred,
                                             boost::disallow_parallel_edge_tag)
      {
        for (incidence_iterator next = first;
             first != last; first = next) {
          ++next;
          if (pred(*first)) {
            if (source(*first, g) != target(*first, g)) {
              // Remove the edge from the target
              detail::remove_directed_edge_dispatch
                (*first, 
                 g.out_edge_list(target(*first, g)), 
                 *(PropT*)(*first).get_property());
            }

            // Erase the edge property
            g.m_edges.erase( (*first.base()).get_iter() );

            // Erase the edge in the source
            el.erase( first.base() );
          }
        }
      }

      // O(E/V)
      template <class edge_descriptor, class EdgeList, class StoredProperty>
      inline void
      remove_directed_edge_dispatch(edge_descriptor e, EdgeList& el,
                                    no_property&)
      {
        for (typename EdgeList::iterator i = el.begin();
             i != el.end(); ++i)
          if ((*i).get_target() == e.m_target) {
            el.erase(i);
            return;
          }
      }

    } // namespace detail

    template <class Config>
    struct directed_edges_helper {

      // Placement of these overloaded remove_edge() functions
      // inside the class avoids a VC++ bug.
      
      // O(E/V)
      inline void
      remove_edge(typename Config::edge_descriptor e)
      {
        typedef typename Config::graph_type graph_type;
        graph_type& g = static_cast<graph_type&>(*this);
        typename Config::OutEdgeList& el = g.out_edge_list(source(e, g));
        typedef typename Config::OutEdgeList::value_type::property_type PType;
        detail::remove_directed_edge_dispatch(e, el,
                                              *(PType*)e.get_property());
      }

      // O(1)
      inline void
      remove_edge(typename Config::out_edge_iterator iter)
      {
        typedef typename Config::graph_type graph_type;
        graph_type& g = static_cast<graph_type&>(*this);
        typename Config::edge_descriptor e = *iter;
        typename Config::OutEdgeList& el = g.out_edge_list(source(e, g));
        el.erase(iter.base());
      }

    };

    // O(1)
    template <class Config>
    inline std::pair<typename Config::edge_iterator, 
                     typename Config::edge_iterator>
    edges(const directed_edges_helper<Config>& g_)
    {
      typedef typename Config::graph_type graph_type;
      typedef typename Config::edge_iterator edge_iterator;
      const graph_type& cg = static_cast<const graph_type&>(g_);
      graph_type& g = const_cast<graph_type&>(cg);
      return std::make_pair( edge_iterator(g.vertex_set().begin(), 
                                           g.vertex_set().begin(), 
                                           g.vertex_set().end(), g),
                             edge_iterator(g.vertex_set().begin(),
                                           g.vertex_set().end(),
                                           g.vertex_set().end(), g) );
    }

    //=========================================================================
    // Directed Graph Helper Class

    struct adj_list_dir_traversal_tag :
      public virtual vertex_list_graph_tag,
      public virtual incidence_graph_tag,
      public virtual adjacency_graph_tag,
      public virtual edge_list_graph_tag { };

    template <class Config>
    struct directed_graph_helper
      : public directed_edges_helper<Config> { 
      typedef typename Config::edge_descriptor edge_descriptor;
      typedef adj_list_dir_traversal_tag traversal_category;
    };

    // O(E/V)
    template <class Config>
    inline void
    remove_edge(typename Config::vertex_descriptor u,
                typename Config::vertex_descriptor v,
                directed_graph_helper<Config>& g_)
    {
      typedef typename Config::graph_type graph_type;
      typedef typename Config::edge_parallel_category Cat;
      graph_type& g = static_cast<graph_type&>(g_);
      detail::erase_from_incidence_list(g.out_edge_list(u), v, Cat());
    }

    template <class Config, class Predicate>
    inline void
    remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred,
                       directed_graph_helper<Config>& g_)
    {
      typedef typename Config::graph_type graph_type;
      graph_type& g = static_cast<graph_type&>(g_);
      typename Config::out_edge_iterator first, last;
      tie(first, last) = out_edges(u, g);
      typedef typename Config::edge_parallel_category edge_parallel_category;
      detail::remove_directed_edge_if_dispatch
        (first, last, g.out_edge_list(u), pred, edge_parallel_category());
    }

    template <class Config, class Predicate>
    inline void
    remove_edge_if(Predicate pred, directed_graph_helper<Config>& g_)
    {
      typedef typename Config::graph_type graph_type;
      graph_type& g = static_cast<graph_type&>(g_);

      typename Config::vertex_iterator vi, vi_end;
      for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
        remove_out_edge_if(*vi, pred, g);
    }    

    template <class EdgeOrIter, class Config>
    inline void
    remove_edge(EdgeOrIter e_or_iter, directed_graph_helper<Config>& g_)
    {
      g_.remove_edge(e_or_iter);
    }

    // O(V + E) for allow_parallel_edges
    // O(V * log(E/V)) for disallow_parallel_edges
    template <class Config>
    inline void 
    clear_vertex(typename Config::vertex_descriptor u,
                 directed_graph_helper<Config>& g_)
    {
      typedef typename Config::graph_type graph_type;
      typedef typename Config::edge_parallel_category Cat;
      graph_type& g = static_cast<graph_type&>(g_);
      typename Config::vertex_iterator vi, viend;
      for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi)
        detail::erase_from_incidence_list(g.out_edge_list(*vi), u, Cat());
      g.out_edge_list(u).clear();
      // clear() should be a req of Sequence and AssociativeContainer,
      // or maybe just Container
    }

    template <class Config>
    inline void 
    clear_out_edges(typename Config::vertex_descriptor u,
                    directed_graph_helper<Config>& g_)
    {
      typedef typename Config::graph_type graph_type;
      typedef typename Config::edge_parallel_category Cat;
      graph_type& g = static_cast<graph_type&>(g_);
      g.out_edge_list(u).clear();
      // clear() should be a req of Sequence and AssociativeContainer,
      // or maybe just Container
    }

    // O(V), could do better...
    template <class Config>
    inline typename Config::edges_size_type
    num_edges(const directed_graph_helper<Config>& g_)
    {
      typedef typename Config::graph_type graph_type;
      const graph_type& g = static_cast<const graph_type&>(g_);
      typename Config::edges_size_type num_e = 0;
      typename Config::vertex_iterator vi, vi_end;
      for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
        num_e += out_degree(*vi, g);
      return num_e;
    }
    // O(1) for allow_parallel_edge_tag
    // O(log(E/V)) for disallow_parallel_edge_tag
    template <class Config>
    inline std::pair<typename directed_graph_helper<Config>::edge_descriptor, bool>
    add_edge(typename Config::vertex_descriptor u, 
             typename Config::vertex_descriptor v,
             const typename Config::edge_property_type& p, 
             directed_graph_helper<Config>& g_)
    {
      typedef typename Config::edge_descriptor edge_descriptor;
      typedef typename Config::graph_type graph_type;
      typedef typename Config::StoredEdge StoredEdge;
      graph_type& g = static_cast<graph_type&>(g_);
      typename Config::OutEdgeList::iterator i; 
      bool inserted;
      boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), 
                                            StoredEdge(v, p));
      return std::make_pair(edge_descriptor(u, v, &(*i).get_property()), 
                            inserted);
    }
    // Did not use default argument here because that

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -