blob: e86b9db439b8d6542843ef09e1e5bab70614f31a [file] [log] [blame]
//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
//
//
// Revision History:
// 13 June 2001: Changed some names for clarity. (Jeremy Siek)
// 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock)
//
#ifndef BOOST_GRAPH_DETAIL_BUCKET_SORTER_HPP
#define BOOST_GRAPH_DETAIL_BUCKET_SORTER_HPP
#include <vector>
#include <cassert>
#include <boost/limits.hpp>
namespace boost {
template <class BucketType, class ValueType, class Bucket,
class ValueIndexMap>
class bucket_sorter {
public:
typedef BucketType bucket_type;
typedef ValueType value_type;
typedef typename std::vector<value_type>::size_type size_type;
bucket_sorter(size_type _length, bucket_type _max_bucket,
const Bucket& _bucket = Bucket(),
const ValueIndexMap& _id = ValueIndexMap())
: head(_max_bucket, invalid_value()),
next(_length, invalid_value()),
prev(_length, invalid_value()),
id_to_value(_length),
bucket(_bucket), id(_id) { }
void remove(const value_type& x) {
const size_type i = get(id, x);
const size_type& next_node = next[i];
const size_type& prev_node = prev[i];
//check if i is the end of the bucket list
if ( next_node != invalid_value() )
prev[next_node] = prev_node;
//check if i is the begin of the bucket list
if ( prev_node != invalid_value() )
next[prev_node] = next_node;
else //need update head of current bucket list
head[ bucket[x] ] = next_node;
}
void push(const value_type& x) {
id_to_value[get(id, x)] = x;
(*this)[bucket[x]].push(x);
}
void update(const value_type& x) {
remove(x);
(*this)[bucket[x]].push(x);
}
// private:
// with KCC, the nested stack class is having access problems
// despite the friend decl.
static size_type invalid_value() {
return (std::numeric_limits<size_type>::max)();
}
typedef typename std::vector<size_type>::iterator Iter;
typedef typename std::vector<value_type>::iterator IndexValueMap;
public:
friend class stack;
class stack {
public:
stack(bucket_type _bucket_id, Iter h, Iter n, Iter p, IndexValueMap v,
const ValueIndexMap& _id)
: bucket_id(_bucket_id), head(h), next(n), prev(p), value(v), id(_id) {}
// Avoid using default arg for ValueIndexMap so that the default
// constructor of the ValueIndexMap is not required if not used.
stack(bucket_type _bucket_id, Iter h, Iter n, Iter p, IndexValueMap v)
: bucket_id(_bucket_id), head(h), next(n), prev(p), value(v) {}
void push(const value_type& x) {
const size_type new_head = get(id, x);
const size_type current = head[bucket_id];
if ( current != invalid_value() )
prev[current] = new_head;
prev[new_head] = invalid_value();
next[new_head] = current;
head[bucket_id] = new_head;
}
void pop() {
size_type current = head[bucket_id];
size_type next_node = next[current];
head[bucket_id] = next_node;
if ( next_node != invalid_value() )
prev[next_node] = invalid_value();
}
value_type& top() { return value[ head[bucket_id] ]; }
const value_type& top() const { return value[ head[bucket_id] ]; }
bool empty() const { return head[bucket_id] == invalid_value(); }
private:
bucket_type bucket_id;
Iter head;
Iter next;
Iter prev;
IndexValueMap value;
ValueIndexMap id;
};
stack operator[](const bucket_type& i) {
assert(i < head.size());
return stack(i, head.begin(), next.begin(), prev.begin(),
id_to_value.begin(), id);
}
protected:
std::vector<size_type> head;
std::vector<size_type> next;
std::vector<size_type> prev;
std::vector<value_type> id_to_value;
Bucket bucket;
ValueIndexMap id;
};
}
#endif