lemon/bucket_heap.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2089 fce8db723736
child 2263 9273fe7d850c
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
deba@2038
     1
/* -*- C++ -*-
deba@2038
     2
 *
deba@2038
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@2038
     4
 *
deba@2038
     5
 * Copyright (C) 2003-2006
deba@2038
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@2038
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@2038
     8
 *
deba@2038
     9
 * Permission to use, modify and distribute this software is granted
deba@2038
    10
 * provided that this copyright notice appears in all copies. For
deba@2038
    11
 * precise terms see the accompanying LICENSE file.
deba@2038
    12
 *
deba@2038
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@2038
    14
 * express or implied, and with no claim as to its suitability for any
deba@2038
    15
 * purpose.
deba@2038
    16
 *
deba@2038
    17
 */
deba@2038
    18
deba@2038
    19
#ifndef LEMON_BUCKET_HEAP_H
deba@2038
    20
#define LEMON_BUCKET_HEAP_H
deba@2038
    21
deba@2038
    22
///\ingroup auxdat
deba@2038
    23
///\file
deba@2038
    24
///\brief Bucket Heap implementation.
deba@2038
    25
deba@2038
    26
#include <vector>
deba@2038
    27
#include <utility>
deba@2038
    28
#include <functional>
deba@2038
    29
deba@2038
    30
namespace lemon {
deba@2038
    31
deba@2038
    32
  /// \ingroup auxdat
deba@2089
    33
  ///
deba@2038
    34
  /// \brief A Bucket Heap implementation.
deba@2038
    35
  ///
deba@2038
    36
  /// This class implements the \e bucket \e heap data structure. A \e heap
deba@2038
    37
  /// is a data structure for storing items with specified values called \e
deba@2038
    38
  /// priorities in such a way that finding the item with minimum priority is
deba@2038
    39
  /// efficient. The bucket heap is very simple implementation, it can store
deba@2042
    40
  /// only integer priorities and it stores for each priority in the 
deba@2042
    41
  /// \f$ [0..C) \f$ range a list of items. So it should be used only when 
deba@2042
    42
  /// the priorities are small. It is not intended to use as dijkstra heap.
deba@2038
    43
  ///
deba@2038
    44
  /// \param _Item Type of the items to be stored.  
deba@2038
    45
  /// \param _ItemIntMap A read and writable Item int map, used internally
deba@2038
    46
  /// to handle the cross references.
deba@2038
    47
  /// \param minimize If the given parameter is true then the heap gives back
deba@2038
    48
  /// the lowest priority. 
deba@2038
    49
  template <typename _Item, typename _ItemIntMap, bool minimize = true >
deba@2038
    50
  class BucketHeap {
deba@2038
    51
deba@2038
    52
  public:
deba@2038
    53
    typedef _Item Item;
deba@2038
    54
    typedef int Prio;
deba@2038
    55
    typedef std::pair<Item, Prio> Pair;
deba@2038
    56
    typedef _ItemIntMap ItemIntMap;
deba@2038
    57
deba@2038
    58
    /// \brief Type to represent the items states.
deba@2038
    59
    ///
deba@2038
    60
    /// Each Item element have a state associated to it. It may be "in heap",
deba@2038
    61
    /// "pre heap" or "post heap". The latter two are indifferent from the
deba@2038
    62
    /// heap's point of view, but may be useful to the user.
deba@2038
    63
    ///
deba@2038
    64
    /// The ItemIntMap \e should be initialized in such way that it maps
deba@2038
    65
    /// PRE_HEAP (-1) to any element to be put in the heap...
deba@2038
    66
    enum state_enum {
deba@2038
    67
      IN_HEAP = 0,
deba@2038
    68
      PRE_HEAP = -1,
deba@2038
    69
      POST_HEAP = -2
deba@2038
    70
    };
deba@2038
    71
deba@2038
    72
  public:
deba@2038
    73
    /// \brief The constructor.
deba@2038
    74
    ///
deba@2038
    75
    /// The constructor.
deba@2038
    76
    /// \param _index should be given to the constructor, since it is used
deba@2038
    77
    /// internally to handle the cross references. The value of the map
deba@2038
    78
    /// should be PRE_HEAP (-1) for each element.
deba@2038
    79
    explicit BucketHeap(ItemIntMap &_index) : index(_index), minimal(0) {}
deba@2038
    80
    
deba@2038
    81
    /// The number of items stored in the heap.
deba@2038
    82
    ///
deba@2038
    83
    /// \brief Returns the number of items stored in the heap.
deba@2038
    84
    int size() const { return data.size(); }
deba@2038
    85
    
deba@2038
    86
    /// \brief Checks if the heap stores no items.
deba@2038
    87
    ///
deba@2038
    88
    /// Returns \c true if and only if the heap stores no items.
deba@2038
    89
    bool empty() const { return data.empty(); }
deba@2038
    90
deba@2038
    91
    /// \brief Make empty this heap.
deba@2038
    92
    /// 
deba@2050
    93
    /// Make empty this heap. It does not change the cross reference
deba@2050
    94
    /// map.  If you want to reuse a heap what is not surely empty you
deba@2050
    95
    /// should first clear the heap and after that you should set the
deba@2050
    96
    /// cross reference map for each item to \c PRE_HEAP.
deba@2038
    97
    void clear() { 
deba@2038
    98
      data.clear(); first.clear(); minimal = 0;
deba@2038
    99
    }
deba@2038
   100
deba@2038
   101
  private:
deba@2038
   102
deba@2038
   103
    void relocate_last(int idx) {
deba@2038
   104
      if (idx + 1 < (int)data.size()) {
deba@2038
   105
	data[idx] = data.back();
deba@2038
   106
	if (data[idx].prev != -1) {
deba@2038
   107
	  data[data[idx].prev].next = idx;
deba@2038
   108
	} else {
deba@2038
   109
	  first[data[idx].value] = idx;
deba@2038
   110
	}
deba@2038
   111
	if (data[idx].next != -1) {
deba@2038
   112
	  data[data[idx].next].prev = idx;
deba@2038
   113
	}
deba@2038
   114
	index[data[idx].item] = idx;
deba@2038
   115
      }
deba@2038
   116
      data.pop_back();
deba@2038
   117
    }
deba@2038
   118
deba@2038
   119
    void unlace(int idx) {
deba@2038
   120
      if (data[idx].prev != -1) {
deba@2038
   121
	data[data[idx].prev].next = data[idx].next;
deba@2038
   122
      } else {
deba@2038
   123
	first[data[idx].value] = data[idx].next;
deba@2038
   124
      }
deba@2038
   125
      if (data[idx].next != -1) {
deba@2038
   126
	data[data[idx].next].prev = data[idx].prev;
deba@2038
   127
      }
deba@2038
   128
    }
deba@2038
   129
deba@2038
   130
    void lace(int idx) {
deba@2038
   131
      if ((int)first.size() <= data[idx].value) {
deba@2038
   132
	first.resize(data[idx].value + 1, -1);
deba@2038
   133
      }
deba@2038
   134
      data[idx].next = first[data[idx].value];
deba@2038
   135
      if (data[idx].next != -1) {
deba@2038
   136
	data[data[idx].next].prev = idx;
deba@2038
   137
      }
deba@2038
   138
      first[data[idx].value] = idx;
deba@2038
   139
      data[idx].prev = -1;
deba@2038
   140
    }
deba@2038
   141
deba@2038
   142
  public:
deba@2038
   143
    /// \brief Insert a pair of item and priority into the heap.
deba@2038
   144
    ///
deba@2038
   145
    /// Adds \c p.first to the heap with priority \c p.second.
deba@2038
   146
    /// \param p The pair to insert.
deba@2038
   147
    void push(const Pair& p) {
deba@2038
   148
      push(p.first, p.second);
deba@2038
   149
    }
deba@2038
   150
deba@2038
   151
    /// \brief Insert an item into the heap with the given priority.
deba@2038
   152
    ///    
deba@2038
   153
    /// Adds \c i to the heap with priority \c p. 
deba@2038
   154
    /// \param i The item to insert.
deba@2038
   155
    /// \param p The priority of the item.
deba@2038
   156
    void push(const Item &i, const Prio &p) { 
deba@2038
   157
      int idx = data.size();
deba@2038
   158
      index[i] = idx;
deba@2038
   159
      data.push_back(BucketItem(i, p));
deba@2038
   160
      lace(idx);
deba@2038
   161
      if (p < minimal) {
deba@2038
   162
	minimal = p;
deba@2038
   163
      }
deba@2038
   164
    }
deba@2038
   165
deba@2038
   166
    /// \brief Returns the item with minimum priority.
deba@2038
   167
    ///
deba@2038
   168
    /// This method returns the item with minimum priority.
deba@2038
   169
    /// \pre The heap must be nonempty.  
deba@2038
   170
    Item top() const {
deba@2038
   171
      while (first[minimal] == -1) {
deba@2038
   172
	++minimal;
deba@2038
   173
      }
deba@2038
   174
      return data[first[minimal]].item;
deba@2038
   175
    }
deba@2038
   176
deba@2038
   177
    /// \brief Returns the minimum priority.
deba@2038
   178
    ///
deba@2038
   179
    /// It returns the minimum priority.
deba@2038
   180
    /// \pre The heap must be nonempty.
deba@2038
   181
    Prio prio() const {
deba@2038
   182
      while (first[minimal] == -1) {
deba@2038
   183
	++minimal;
deba@2038
   184
      }
deba@2038
   185
      return minimal;
deba@2038
   186
    }
deba@2038
   187
deba@2038
   188
    /// \brief Deletes the item with minimum priority.
deba@2038
   189
    ///
deba@2038
   190
    /// This method deletes the item with minimum priority from the heap.  
deba@2038
   191
    /// \pre The heap must be non-empty.  
deba@2038
   192
    void pop() {
deba@2038
   193
      while (first[minimal] == -1) {
deba@2038
   194
	++minimal;
deba@2038
   195
      }
deba@2038
   196
      int idx = first[minimal];
deba@2038
   197
      index[data[idx].item] = -2;
deba@2038
   198
      unlace(idx);
deba@2038
   199
      relocate_last(idx);
deba@2038
   200
    }
deba@2038
   201
deba@2038
   202
    /// \brief Deletes \c i from the heap.
deba@2038
   203
    ///
deba@2038
   204
    /// This method deletes item \c i from the heap, if \c i was
deba@2038
   205
    /// already stored in the heap.
deba@2038
   206
    /// \param i The item to erase. 
deba@2038
   207
    void erase(const Item &i) {
deba@2038
   208
      int idx = index[i];
deba@2038
   209
      index[data[idx].item] = -2;
deba@2038
   210
      unlace(idx);
deba@2038
   211
      relocate_last(idx);
deba@2038
   212
    }
deba@2038
   213
deba@2038
   214
    
deba@2038
   215
    /// \brief Returns the priority of \c i.
deba@2038
   216
    ///
deba@2038
   217
    /// This function returns the priority of item \c i.  
deba@2038
   218
    /// \pre \c i must be in the heap.
deba@2038
   219
    /// \param i The item.
deba@2038
   220
    Prio operator[](const Item &i) const {
deba@2038
   221
      int idx = index[i];
deba@2038
   222
      return data[idx].value;
deba@2038
   223
    }
deba@2038
   224
deba@2038
   225
    /// \brief \c i gets to the heap with priority \c p independently 
deba@2038
   226
    /// if \c i was already there.
deba@2038
   227
    ///
deba@2038
   228
    /// This method calls \ref push(\c i, \c p) if \c i is not stored
deba@2038
   229
    /// in the heap and sets the priority of \c i to \c p otherwise.
deba@2038
   230
    /// \param i The item.
deba@2038
   231
    /// \param p The priority.
deba@2038
   232
    void set(const Item &i, const Prio &p) {
deba@2038
   233
      int idx = index[i];
deba@2038
   234
      if (idx < 0) {
deba@2038
   235
	push(i,p);
deba@2038
   236
      } else if (p > data[idx].value) {
deba@2038
   237
	increase(i, p);
deba@2038
   238
      } else {
deba@2038
   239
	decrease(i, p);
deba@2038
   240
      }
deba@2038
   241
    }
deba@2038
   242
deba@2038
   243
    /// \brief Decreases the priority of \c i to \c p.
deba@2089
   244
    ///
deba@2038
   245
    /// This method decreases the priority of item \c i to \c p.
deba@2038
   246
    /// \pre \c i must be stored in the heap with priority at least \c
deba@2038
   247
    /// p relative to \c Compare.
deba@2038
   248
    /// \param i The item.
deba@2038
   249
    /// \param p The priority.
deba@2038
   250
    void decrease(const Item &i, const Prio &p) {
deba@2038
   251
      int idx = index[i];
deba@2038
   252
      unlace(idx);
deba@2038
   253
      data[idx].value = p;
deba@2038
   254
      if (p < minimal) {
deba@2038
   255
	minimal = p;
deba@2038
   256
      }
deba@2038
   257
      lace(idx);
deba@2038
   258
    }
deba@2038
   259
    
deba@2038
   260
    /// \brief Increases the priority of \c i to \c p.
deba@2038
   261
    ///
deba@2038
   262
    /// This method sets the priority of item \c i to \c p. 
deba@2038
   263
    /// \pre \c i must be stored in the heap with priority at most \c
deba@2038
   264
    /// p relative to \c Compare.
deba@2038
   265
    /// \param i The item.
deba@2038
   266
    /// \param p The priority.
deba@2038
   267
    void increase(const Item &i, const Prio &p) {
deba@2038
   268
      int idx = index[i];
deba@2038
   269
      unlace(idx);
deba@2038
   270
      data[idx].value = p;
deba@2038
   271
      lace(idx);
deba@2038
   272
    }
deba@2038
   273
deba@2038
   274
    /// \brief Returns if \c item is in, has already been in, or has 
deba@2038
   275
    /// never been in the heap.
deba@2038
   276
    ///
deba@2038
   277
    /// This method returns PRE_HEAP if \c item has never been in the
deba@2038
   278
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
deba@2038
   279
    /// otherwise. In the latter case it is possible that \c item will
deba@2038
   280
    /// get back to the heap again.
deba@2038
   281
    /// \param i The item.
deba@2038
   282
    state_enum state(const Item &i) const {
deba@2038
   283
      int idx = index[i];
deba@2038
   284
      if (idx >= 0) idx = 0;
deba@2038
   285
      return state_enum(idx);
deba@2038
   286
    }
deba@2038
   287
deba@2038
   288
    /// \brief Sets the state of the \c item in the heap.
deba@2038
   289
    ///
deba@2038
   290
    /// Sets the state of the \c item in the heap. It can be used to
deba@2038
   291
    /// manually clear the heap when it is important to achive the
deba@2038
   292
    /// better time complexity.
deba@2038
   293
    /// \param i The item.
deba@2038
   294
    /// \param st The state. It should not be \c IN_HEAP. 
deba@2038
   295
    void state(const Item& i, state_enum st) {
deba@2038
   296
      switch (st) {
deba@2038
   297
      case POST_HEAP:
deba@2038
   298
      case PRE_HEAP:
deba@2038
   299
        if (state(i) == IN_HEAP) {
deba@2038
   300
          erase(i);
deba@2038
   301
        }
deba@2038
   302
        index[i] = st;
deba@2038
   303
        break;
deba@2038
   304
      case IN_HEAP:
deba@2038
   305
        break;
deba@2038
   306
      }
deba@2038
   307
    }
deba@2038
   308
deba@2038
   309
  private:
deba@2038
   310
deba@2038
   311
    struct BucketItem {
deba@2038
   312
      BucketItem(const Item& _item, int _value) 
deba@2038
   313
	: item(_item), value(_value) {}
deba@2038
   314
deba@2038
   315
      Item item;
deba@2038
   316
      int value;
deba@2038
   317
deba@2038
   318
      int prev, next;
deba@2038
   319
    };
deba@2038
   320
deba@2038
   321
    ItemIntMap& index;
deba@2038
   322
    std::vector<int> first;
deba@2038
   323
    std::vector<BucketItem> data;
deba@2038
   324
    mutable int minimal;
deba@2038
   325
deba@2038
   326
  }; // class BucketHeap
deba@2038
   327
deba@2038
   328
deba@2038
   329
  template <typename _Item, typename _ItemIntMap>
deba@2038
   330
  class BucketHeap<_Item, _ItemIntMap, false> {
deba@2038
   331
deba@2038
   332
  public:
deba@2038
   333
    typedef _Item Item;
deba@2038
   334
    typedef int Prio;
deba@2038
   335
    typedef std::pair<Item, Prio> Pair;
deba@2038
   336
    typedef _ItemIntMap ItemIntMap;
deba@2038
   337
deba@2038
   338
    enum state_enum {
deba@2038
   339
      IN_HEAP = 0,
deba@2038
   340
      PRE_HEAP = -1,
deba@2038
   341
      POST_HEAP = -2
deba@2038
   342
    };
deba@2038
   343
deba@2038
   344
  public:
deba@2038
   345
deba@2038
   346
    explicit BucketHeap(ItemIntMap &_index) : index(_index), maximal(-1) {}
deba@2038
   347
deba@2038
   348
    int size() const { return data.size(); }
deba@2038
   349
    bool empty() const { return data.empty(); }
deba@2038
   350
deba@2038
   351
    void clear() { 
deba@2038
   352
      data.clear(); first.clear(); maximal = -1; 
deba@2038
   353
    }
deba@2038
   354
deba@2038
   355
  private:
deba@2038
   356
deba@2038
   357
    void relocate_last(int idx) {
deba@2038
   358
      if (idx + 1 != (int)data.size()) {
deba@2038
   359
	data[idx] = data.back();
deba@2038
   360
	if (data[idx].prev != -1) {
deba@2038
   361
	  data[data[idx].prev].next = idx;
deba@2038
   362
	} else {
deba@2038
   363
	  first[data[idx].value] = idx;
deba@2038
   364
	}
deba@2038
   365
	if (data[idx].next != -1) {
deba@2038
   366
	  data[data[idx].next].prev = idx;
deba@2038
   367
	}
deba@2038
   368
	index[data[idx].item] = idx;
deba@2038
   369
      }
deba@2038
   370
      data.pop_back();
deba@2038
   371
    }
deba@2038
   372
deba@2038
   373
    void unlace(int idx) {
deba@2038
   374
      if (data[idx].prev != -1) {
deba@2038
   375
	data[data[idx].prev].next = data[idx].next;
deba@2038
   376
      } else {
deba@2038
   377
	first[data[idx].value] = data[idx].next;
deba@2038
   378
      }
deba@2038
   379
      if (data[idx].next != -1) {
deba@2038
   380
	data[data[idx].next].prev = data[idx].prev;
deba@2038
   381
      }
deba@2038
   382
    }
deba@2038
   383
deba@2038
   384
    void lace(int idx) {
deba@2038
   385
      if ((int)first.size() <= data[idx].value) {
deba@2038
   386
	first.resize(data[idx].value + 1, -1);
deba@2038
   387
      }
deba@2038
   388
      data[idx].next = first[data[idx].value];
deba@2038
   389
      if (data[idx].next != -1) {
deba@2038
   390
	data[data[idx].next].prev = idx;
deba@2038
   391
      }
deba@2038
   392
      first[data[idx].value] = idx;
deba@2038
   393
      data[idx].prev = -1;
deba@2038
   394
    }
deba@2038
   395
deba@2038
   396
  public:
deba@2038
   397
deba@2038
   398
    void push(const Pair& p) {
deba@2038
   399
      push(p.first, p.second);
deba@2038
   400
    }
deba@2038
   401
deba@2038
   402
    void push(const Item &i, const Prio &p) { 
deba@2038
   403
      int idx = data.size();
deba@2038
   404
      index[i] = idx;
deba@2038
   405
      data.push_back(BucketItem(i, p));
deba@2038
   406
      lace(idx);
deba@2038
   407
      if (data[idx].value > maximal) {
deba@2038
   408
	maximal = data[idx].value;
deba@2038
   409
      }
deba@2038
   410
    }
deba@2038
   411
deba@2038
   412
    Item top() const {
deba@2038
   413
      while (first[maximal] == -1) {
deba@2038
   414
	--maximal;
deba@2038
   415
      }
deba@2038
   416
      return data[first[maximal]].item;
deba@2038
   417
    }
deba@2038
   418
deba@2038
   419
    Prio prio() const {
deba@2038
   420
      while (first[maximal] == -1) {
deba@2038
   421
	--maximal;
deba@2038
   422
      }
deba@2038
   423
      return maximal;
deba@2038
   424
    }
deba@2038
   425
deba@2038
   426
    void pop() {
deba@2038
   427
      while (first[maximal] == -1) {
deba@2038
   428
	--maximal;
deba@2038
   429
      }
deba@2038
   430
      int idx = first[maximal];
deba@2038
   431
      index[data[idx].item] = -2;
deba@2038
   432
      unlace(idx);
deba@2038
   433
      relocate_last(idx);
deba@2038
   434
    }
deba@2038
   435
deba@2038
   436
    void erase(const Item &i) {
deba@2038
   437
      int idx = index[i];
deba@2038
   438
      index[data[idx].item] = -2;
deba@2038
   439
      unlace(idx);
deba@2038
   440
      relocate_last(idx);
deba@2038
   441
    }
deba@2038
   442
deba@2038
   443
    Prio operator[](const Item &i) const {
deba@2038
   444
      int idx = index[i];
deba@2038
   445
      return data[idx].value;
deba@2038
   446
    }
deba@2038
   447
deba@2038
   448
    void set(const Item &i, const Prio &p) {
deba@2038
   449
      int idx = index[i];
deba@2038
   450
      if (idx < 0) {
deba@2038
   451
	push(i,p);
deba@2038
   452
      } else if (p > data[idx].value) {
deba@2038
   453
	decrease(i, p);
deba@2038
   454
      } else {
deba@2038
   455
	increase(i, p);
deba@2038
   456
      }
deba@2038
   457
    }
deba@2038
   458
deba@2038
   459
    void decrease(const Item &i, const Prio &p) {
deba@2038
   460
      int idx = index[i];
deba@2038
   461
      unlace(idx);
deba@2038
   462
      data[idx].value = p;
deba@2038
   463
      if (p > maximal) {
deba@2038
   464
	maximal = p;
deba@2038
   465
      }
deba@2038
   466
      lace(idx);
deba@2038
   467
    }
deba@2038
   468
    
deba@2038
   469
    void increase(const Item &i, const Prio &p) {
deba@2038
   470
      int idx = index[i];
deba@2038
   471
      unlace(idx);
deba@2038
   472
      data[idx].value = p;
deba@2038
   473
      lace(idx);
deba@2038
   474
    }
deba@2038
   475
deba@2038
   476
    state_enum state(const Item &i) const {
deba@2038
   477
      int idx = index[i];
deba@2038
   478
      if (idx >= 0) idx = 0;
deba@2038
   479
      return state_enum(idx);
deba@2038
   480
    }
deba@2038
   481
deba@2038
   482
    void state(const Item& i, state_enum st) {
deba@2038
   483
      switch (st) {
deba@2038
   484
      case POST_HEAP:
deba@2038
   485
      case PRE_HEAP:
deba@2038
   486
        if (state(i) == IN_HEAP) {
deba@2038
   487
          erase(i);
deba@2038
   488
        }
deba@2038
   489
        index[i] = st;
deba@2038
   490
        break;
deba@2038
   491
      case IN_HEAP:
deba@2038
   492
        break;
deba@2038
   493
      }
deba@2038
   494
    }
deba@2038
   495
deba@2038
   496
  private:
deba@2038
   497
deba@2038
   498
    struct BucketItem {
deba@2038
   499
      BucketItem(const Item& _item, int _value) 
deba@2038
   500
	: item(_item), value(_value) {}
deba@2038
   501
deba@2038
   502
      Item item;
deba@2038
   503
      int value;
deba@2038
   504
deba@2038
   505
      int prev, next;
deba@2038
   506
    };
deba@2038
   507
deba@2038
   508
    ItemIntMap& index;
deba@2038
   509
    std::vector<int> first;
deba@2038
   510
    std::vector<BucketItem> data;
deba@2038
   511
    mutable int maximal;
deba@2038
   512
deba@2038
   513
  }; // class BucketHeap
deba@2038
   514
deba@2089
   515
  /// \ingroup auxdat
deba@2089
   516
  ///
deba@2089
   517
  /// \brief A Simplified Bucket Heap implementation.
deba@2089
   518
  ///
deba@2089
   519
  /// This class implements a simplified \e bucket \e heap data
deba@2089
   520
  /// structure.  It does not provide some functionality but it faster
deba@2089
   521
  /// and simplier data structure than the BucketHeap. The main
deba@2089
   522
  /// difference is that the BucketHeap stores for every key a double
deba@2089
   523
  /// linked list while this class stores just simple lists. In the
deba@2089
   524
  /// other way it does not supports erasing each elements just the
deba@2089
   525
  /// minimal and it does not supports key increasing, decreasing.
deba@2089
   526
  ///
deba@2089
   527
  /// \param _Item Type of the items to be stored.  
deba@2089
   528
  /// \param _ItemIntMap A read and writable Item int map, used internally
deba@2089
   529
  /// to handle the cross references.
deba@2089
   530
  /// \param minimize If the given parameter is true then the heap gives back
deba@2089
   531
  /// the lowest priority.
deba@2089
   532
  ///
deba@2089
   533
  /// \sa BucketHeap 
deba@2089
   534
  template <typename _Item, typename _ItemIntMap, bool minimize = true >
deba@2089
   535
  class SimpleBucketHeap {
deba@2089
   536
deba@2089
   537
  public:
deba@2089
   538
    typedef _Item Item;
deba@2089
   539
    typedef int Prio;
deba@2089
   540
    typedef std::pair<Item, Prio> Pair;
deba@2089
   541
    typedef _ItemIntMap ItemIntMap;
deba@2089
   542
deba@2089
   543
    /// \brief Type to represent the items states.
deba@2089
   544
    ///
deba@2089
   545
    /// Each Item element have a state associated to it. It may be "in heap",
deba@2089
   546
    /// "pre heap" or "post heap". The latter two are indifferent from the
deba@2089
   547
    /// heap's point of view, but may be useful to the user.
deba@2089
   548
    ///
deba@2089
   549
    /// The ItemIntMap \e should be initialized in such way that it maps
deba@2089
   550
    /// PRE_HEAP (-1) to any element to be put in the heap...
deba@2089
   551
    enum state_enum {
deba@2089
   552
      IN_HEAP = 0,
deba@2089
   553
      PRE_HEAP = -1,
deba@2089
   554
      POST_HEAP = -2
deba@2089
   555
    };
deba@2089
   556
deba@2089
   557
  public:
deba@2089
   558
deba@2089
   559
    /// \brief The constructor.
deba@2089
   560
    ///
deba@2089
   561
    /// The constructor.
deba@2089
   562
    /// \param _index should be given to the constructor, since it is used
deba@2089
   563
    /// internally to handle the cross references. The value of the map
deba@2089
   564
    /// should be PRE_HEAP (-1) for each element.
deba@2089
   565
    explicit SimpleBucketHeap(ItemIntMap &_index) 
deba@2089
   566
      : index(_index), free(-1), num(0), minimal(0) {}
deba@2089
   567
    
deba@2089
   568
    /// \brief Returns the number of items stored in the heap.
deba@2089
   569
    ///
deba@2089
   570
    /// The number of items stored in the heap.
deba@2089
   571
    int size() const { return num; }
deba@2089
   572
    
deba@2089
   573
    /// \brief Checks if the heap stores no items.
deba@2089
   574
    ///
deba@2089
   575
    /// Returns \c true if and only if the heap stores no items.
deba@2089
   576
    bool empty() const { return num == 0; }
deba@2089
   577
deba@2089
   578
    /// \brief Make empty this heap.
deba@2089
   579
    /// 
deba@2089
   580
    /// Make empty this heap. It does not change the cross reference
deba@2089
   581
    /// map.  If you want to reuse a heap what is not surely empty you
deba@2089
   582
    /// should first clear the heap and after that you should set the
deba@2089
   583
    /// cross reference map for each item to \c PRE_HEAP.
deba@2089
   584
    void clear() { 
deba@2089
   585
      data.clear(); first.clear(); free = -1; num = 0; minimal = 0;
deba@2089
   586
    }
deba@2089
   587
deba@2089
   588
    /// \brief Insert a pair of item and priority into the heap.
deba@2089
   589
    ///
deba@2089
   590
    /// Adds \c p.first to the heap with priority \c p.second.
deba@2089
   591
    /// \param p The pair to insert.
deba@2089
   592
    void push(const Pair& p) {
deba@2089
   593
      push(p.first, p.second);
deba@2089
   594
    }
deba@2089
   595
deba@2089
   596
    /// \brief Insert an item into the heap with the given priority.
deba@2089
   597
    ///    
deba@2089
   598
    /// Adds \c i to the heap with priority \c p. 
deba@2089
   599
    /// \param i The item to insert.
deba@2089
   600
    /// \param p The priority of the item.
deba@2089
   601
    void push(const Item &i, const Prio &p) {
deba@2089
   602
      int idx;
deba@2089
   603
      if (free == -1) {
deba@2089
   604
        idx = data.size();
deba@2110
   605
        data.push_back(BucketItem(i));
deba@2089
   606
      } else {
deba@2089
   607
        idx = free;
deba@2089
   608
        free = data[idx].next;
deba@2110
   609
        data[idx].item = i;
deba@2089
   610
      }
deba@2089
   611
      index[i] = idx;
deba@2089
   612
      if (p >= (int)first.size()) first.resize(p + 1, -1);
deba@2089
   613
      data[idx].next = first[p];
deba@2089
   614
      first[p] = idx;
deba@2089
   615
      if (p < minimal) {
deba@2089
   616
	minimal = p;
deba@2089
   617
      }
deba@2089
   618
      ++num;
deba@2089
   619
    }
deba@2089
   620
deba@2089
   621
    /// \brief Returns the item with minimum priority.
deba@2089
   622
    ///
deba@2089
   623
    /// This method returns the item with minimum priority.
deba@2089
   624
    /// \pre The heap must be nonempty.  
deba@2089
   625
    Item top() const {
deba@2089
   626
      while (first[minimal] == -1) {
deba@2089
   627
	++minimal;
deba@2089
   628
      }
deba@2089
   629
      return data[first[minimal]].item;
deba@2089
   630
    }
deba@2089
   631
deba@2089
   632
    /// \brief Returns the minimum priority.
deba@2089
   633
    ///
deba@2089
   634
    /// It returns the minimum priority.
deba@2089
   635
    /// \pre The heap must be nonempty.
deba@2089
   636
    Prio prio() const {
deba@2089
   637
      while (first[minimal] == -1) {
deba@2089
   638
	++minimal;
deba@2089
   639
      }
deba@2089
   640
      return minimal;
deba@2089
   641
    }
deba@2089
   642
deba@2089
   643
    /// \brief Deletes the item with minimum priority.
deba@2089
   644
    ///
deba@2089
   645
    /// This method deletes the item with minimum priority from the heap.  
deba@2089
   646
    /// \pre The heap must be non-empty.  
deba@2089
   647
    void pop() {
deba@2089
   648
      while (first[minimal] == -1) {
deba@2089
   649
	++minimal;
deba@2089
   650
      }
deba@2089
   651
      int idx = first[minimal];
deba@2089
   652
      index[data[idx].item] = -2;
deba@2089
   653
      first[minimal] = data[idx].next;
deba@2089
   654
      data[idx].next = free;
deba@2089
   655
      free = idx;
deba@2089
   656
      --num;
deba@2089
   657
    }
deba@2089
   658
    
deba@2089
   659
    /// \brief Returns the priority of \c i.
deba@2089
   660
    ///
deba@2110
   661
    /// This function returns the priority of item \c i.
deba@2110
   662
    /// \warning This operator is not a constant time function
deba@2110
   663
    /// because it scans the whole data structure to find the proper
deba@2110
   664
    /// value.  
deba@2089
   665
    /// \pre \c i must be in the heap.
deba@2089
   666
    /// \param i The item.
deba@2089
   667
    Prio operator[](const Item &i) const {
deba@2110
   668
      for (int k = 0; k < first.size(); ++k) {
deba@2110
   669
        int idx = first[k];
deba@2110
   670
        while (idx != -1) {
deba@2110
   671
          if (data[idx].item == i) {
deba@2110
   672
            return k;
deba@2110
   673
          }
deba@2110
   674
          idx = data[idx].next;
deba@2110
   675
        }
deba@2110
   676
      }
deba@2110
   677
      return -1;
deba@2089
   678
    }
deba@2089
   679
deba@2089
   680
    /// \brief Returns if \c item is in, has already been in, or has 
deba@2089
   681
    /// never been in the heap.
deba@2089
   682
    ///
deba@2089
   683
    /// This method returns PRE_HEAP if \c item has never been in the
deba@2089
   684
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
deba@2089
   685
    /// otherwise. In the latter case it is possible that \c item will
deba@2089
   686
    /// get back to the heap again.
deba@2089
   687
    /// \param i The item.
deba@2089
   688
    state_enum state(const Item &i) const {
deba@2089
   689
      int idx = index[i];
deba@2089
   690
      if (idx >= 0) idx = 0;
deba@2089
   691
      return state_enum(idx);
deba@2089
   692
    }
deba@2089
   693
deba@2089
   694
  private:
deba@2089
   695
deba@2089
   696
    struct BucketItem {
deba@2110
   697
      BucketItem(const Item& _item) 
deba@2110
   698
	: item(_item) {}
deba@2089
   699
deba@2089
   700
      Item item;
deba@2089
   701
      int next;
deba@2089
   702
    };
deba@2089
   703
deba@2089
   704
    ItemIntMap& index;
deba@2089
   705
    std::vector<int> first;
deba@2089
   706
    std::vector<BucketItem> data;
deba@2089
   707
    int free, num;
deba@2089
   708
    mutable int minimal;
deba@2089
   709
deba@2089
   710
  }; // class SimpleBucketHeap
deba@2089
   711
deba@2089
   712
  template <typename _Item, typename _ItemIntMap>
deba@2089
   713
  class SimpleBucketHeap<_Item, _ItemIntMap, false> {
deba@2089
   714
deba@2089
   715
  public:
deba@2089
   716
    typedef _Item Item;
deba@2089
   717
    typedef int Prio;
deba@2089
   718
    typedef std::pair<Item, Prio> Pair;
deba@2089
   719
    typedef _ItemIntMap ItemIntMap;
deba@2089
   720
deba@2089
   721
    enum state_enum {
deba@2089
   722
      IN_HEAP = 0,
deba@2089
   723
      PRE_HEAP = -1,
deba@2089
   724
      POST_HEAP = -2
deba@2089
   725
    };
deba@2089
   726
deba@2089
   727
  public:
deba@2089
   728
deba@2089
   729
    explicit SimpleBucketHeap(ItemIntMap &_index) 
deba@2089
   730
      : index(_index), free(-1), num(0), maximal(0) {}
deba@2089
   731
    
deba@2089
   732
    int size() const { return num; }
deba@2089
   733
    
deba@2089
   734
    bool empty() const { return num == 0; }
deba@2089
   735
deba@2089
   736
    void clear() { 
deba@2089
   737
      data.clear(); first.clear(); free = -1; num = 0; maximal = 0;
deba@2089
   738
    }
deba@2089
   739
deba@2089
   740
    void push(const Pair& p) {
deba@2089
   741
      push(p.first, p.second);
deba@2089
   742
    }
deba@2089
   743
deba@2089
   744
    void push(const Item &i, const Prio &p) {
deba@2089
   745
      int idx;
deba@2089
   746
      if (free == -1) {
deba@2089
   747
        idx = data.size();
deba@2110
   748
        data.push_back(BucketItem(i));
deba@2089
   749
      } else {
deba@2089
   750
        idx = free;
deba@2089
   751
        free = data[idx].next;
deba@2110
   752
        data[idx].item = i;
deba@2089
   753
      }
deba@2089
   754
      index[i] = idx;
deba@2089
   755
      if (p >= (int)first.size()) first.resize(p + 1, -1);
deba@2089
   756
      data[idx].next = first[p];
deba@2089
   757
      first[p] = idx;
deba@2089
   758
      if (p > maximal) {
deba@2089
   759
	maximal = p;
deba@2089
   760
      }
deba@2089
   761
      ++num;
deba@2089
   762
    }
deba@2089
   763
deba@2089
   764
    Item top() const {
deba@2089
   765
      while (first[maximal] == -1) {
deba@2089
   766
	--maximal;
deba@2089
   767
      }
deba@2089
   768
      return data[first[maximal]].item;
deba@2089
   769
    }
deba@2089
   770
deba@2089
   771
    Prio prio() const {
deba@2089
   772
      while (first[maximal] == -1) {
deba@2089
   773
	--maximal;
deba@2089
   774
      }
deba@2089
   775
      return maximal;
deba@2089
   776
    }
deba@2089
   777
deba@2089
   778
    void pop() {
deba@2089
   779
      while (first[maximal] == -1) {
deba@2089
   780
	--maximal;
deba@2089
   781
      }
deba@2089
   782
      int idx = first[maximal];
deba@2089
   783
      index[data[idx].item] = -2;
deba@2089
   784
      first[maximal] = data[idx].next;
deba@2089
   785
      data[idx].next = free;
deba@2089
   786
      free = idx;
deba@2089
   787
      --num;
deba@2089
   788
    }
deba@2089
   789
    
deba@2089
   790
    Prio operator[](const Item &i) const {
deba@2110
   791
      for (int k = 0; k < first.size(); ++k) {
deba@2110
   792
        int idx = first[k];
deba@2110
   793
        while (idx != -1) {
deba@2110
   794
          if (data[idx].item == i) {
deba@2110
   795
            return k;
deba@2110
   796
          }
deba@2110
   797
          idx = data[idx].next;
deba@2110
   798
        }
deba@2110
   799
      }
deba@2110
   800
      return -1;
deba@2089
   801
    }
deba@2089
   802
deba@2089
   803
    state_enum state(const Item &i) const {
deba@2089
   804
      int idx = index[i];
deba@2089
   805
      if (idx >= 0) idx = 0;
deba@2089
   806
      return state_enum(idx);
deba@2089
   807
    }
deba@2089
   808
deba@2089
   809
  private:
deba@2089
   810
deba@2089
   811
    struct BucketItem {
deba@2110
   812
      BucketItem(const Item& _item) : item(_item) {}
deba@2089
   813
deba@2089
   814
      Item item;
deba@2089
   815
deba@2089
   816
      int next;
deba@2089
   817
    };
deba@2089
   818
deba@2089
   819
    ItemIntMap& index;
deba@2089
   820
    std::vector<int> first;
deba@2089
   821
    std::vector<BucketItem> data;
deba@2089
   822
    int free, num;
deba@2089
   823
    mutable int maximal;
deba@2089
   824
deba@2089
   825
  };
deba@2089
   826
deba@2038
   827
}
deba@2038
   828
  
deba@2038
   829
#endif