| # Template class `radix_heap<T, traits>` # Synopsis
    #include "boost/r_heap.hpp"

    template <typename T, int b = 32>
    class boost::radix_traits
    {
      static int const bits = b;
      static unsigned long value(T val);
      static int radix(T val, unsigned long offset);
    };

    template <typename T, typename traits = boost::radix_traits<T> >
    class boost::radix_heap
    {
    public:
      class iterator
      {
      public:
        iterator();

        T const& operator* () const;
        T const* operator->() const;

        iterator& operator++();
        iterator  operator++(int);

        bool operator== (iterator const& it);
        bool operator!= (iterator const& it);
      };

      typedef T        value_type;
      typedef T&       reference;
      typedef T const& const_reference;
      typedef iterator const_iterator;
      typedef int      size_type;
      typedef node*    pointer;

      radix_heap();
      ~radix_heap();

      void      remove(pointer);             // sorry, not yet implemented
      void      change(pointer, T const&);   // sorry, not yet implemented
      void      change_top(T const&);        // sorry, not yet implemented
      void      decrease(pointer, T const&); // sorry, not yet implemented
      void      increase(pointer, T const&); // sorry, not yet implemented

      bool      empty() const;
      size_type size() const;
      pointer   push(T const&);
      T const&  top() const;
      void      pop();

      iterator begin() const;
      iterator end() const;

    private:
      radix_heap(radix_heap const&);      // deliberately not implemented
      void operator= (radix_heap const&); // deliberately not implemented
    };
# Note The current implementation is basically useless because the interesting operations are not implemented at all and some of the implemented operations, notably `push()` make unrealistic assumptions! In the case of `push()` it is assumed that no element was removed from the heap making this heap only useful for cases where `std::sort()` could be used as well (and sorting is much faster). However, I'm sure that the interface can be kept when the code is corrected. # Description The Radix heap cannot be used for general elements because as part of its approach it is restricted to integral types. Also, it is hard to understand the behavior of this approach when using fast access to the largest element. Although the default behavior of this implementation will provide access to the element with the largest priority, the smallest priority is used for the following description... Apart from the restriction on integral types, there is another restriction for the Radix heap, namely that elements cannot be decreased beyond the minimum value currently stored in the heap. A priority queue like this is suitable only in very specific cases but eg. Dijkstra's algorithm to find the shortest paths in a graph is one such application. In turn a radix heap seems to be significantly faster (however, I can't really tell because the current implementation has to be changed to implement the missing operations). The Radix heap maintains a set of buckets and objects with different priority can end up in different buckets. To avoid excessive search for the minimum element, elements are redistributed into unused buckets. Each bucket is assigned a range of elements stored in the bucket where the smaller elements end up in buckets with narrow ranges: Initially, the ranges for the buckets are 0..0, 1..1, 2..3, 4..7, 8..15, and so on. Thus, the correct bucket can be found by determining the radix of the integral value. Now, when elements are removed from the heap, the first buckets become unused and the heap has to search larger buckets for the minimum element. If it has found a bucket with multiple different elements, the heap knows that the smaller buckets are not used. Thus, the elements in the found bucket are redistributed into the unused buckets. The only description of the Radix heap I have currently available (from Network Flows, Ahuja, Magnanti, Orlin, Prentice Hall) is somewhat silent about the details of the operation. Thus, I haven't implemented some of the operations. Also, it probably does not work to insert an element after there are elements extracted from the heap... This class does not use a comparator function. Instead, it uses a traits class which is used to determine the radix of the elements. Actually, the traits class has three members: `bits` This is used as constant expression to determine the number of buckets to be used. This is the maximum value which can be returned from `radix()` plus 1. `value(val)` This function returns an unsigned integral value representing the priority of `val`. This value is used as an offset passed to the `radix()` function. This value could in principle be used to determine the radix but I think that it might be possible provide better function determining the radix than the default one... `radix(val, offset)` This function returns the radix of the priority of `val` minus the offset `offset`. The default traits use a static cast to `unsigned long` to determine the priority of `val`. To cope with the problem that the other priority queues access the largest element first, the value actually used is (well, should be...) `std::numeric_limits<unsigned long>::max() - val`. For a description of the methods of `radix_heap<T, traits>` see the description of common methods. However, keep in mind that the current implementation does not implement all methods and some methods are probably unstable. # Bugs Some of the methods are not yet implemented and other methods are probably buggy. However, I have to work on other stuff and need to get the priority queue off my desk. If you really want to use this class or if you have an idea how to implement the missing methods please contact me. Maybe we can work out how to implement the missing stuff. A paper describing Radix heaps would probably also help... # See Also heap(3), heap-common(3) Copyright © 1999 Dietmar Kühl (dietmar.kuehl@claas-solutions.de) Claas Solutions GmbH