現在位置: ホーム その他 講義関連 FY2009 交通シミュレーション特論 RS_FHeap.h

RS_FHeap.h

Fibonacci Heap の実装

RS_FHeap.h — C header, 17 kB (17544 bytes)

ファイルコンテンツ

// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// RS_FHeap.h --- class RS_FHeap, Fibonacci Heap
// -----
// ChangeLog:
// 2009. 7. 15
//  File complete.
// -----

// ----
// Heap
// ヒープ
// ----

#ifndef RS_FHEAP_H
#define RS_FHEAP_H

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <string>

using std :: cerr ;
using std :: endl ;
using std :: vector ;
using std :: string ;

//#define DEBUG_FHEAP



template < class KC , class ENT >
class RS_FHeap
{
public :

  typedef unsigned int size_type ;

  class Entry
  {

    friend class RS_FHeap ;

  private :

    KC _key ;
    ENT * _ent ;
    typename RS_FHeap :: size_type _deg ;
    bool _marked ;
    typename RS_FHeap :: Entry * _right ;
    typename RS_FHeap :: Entry * _left ;
    typename RS_FHeap :: Entry * _parent ;
    typename RS_FHeap :: Entry * _child ;
    RS_FHeap * _myheap ;

    void cutFromChildList () ;
    void execCascadingCut () ;
    void addToChildList ( Entry * ) ;

    explicit Entry () ;
    explicit Entry ( const Entry & ) ;

  public :

    Entry ( const KC & x , ENT * _e , RS_FHeap * hp )
      : _key ( x ) , _ent ( _e ) , _deg ( 0 ) , _marked ( false ) ,
        _right ( this ) , _left ( this ) , _parent ( 0 ) , _child ( 0 ) ,
        _myheap ( hp ) {}
    
    void decreaseKey ( const KC & ) ;

    const KC & getKey () const { return _key ; }

    Entry * getRight () { return _right ; }
    Entry * getLeft () { return _left ; }
    Entry * getParent () { return _parent ; }
    Entry * getChild () { return _child ; }
    typename RS_FHeap :: size_type getDegree () const { return _deg ; }
    typename RS_FHeap :: size_type countEntriesInMe () const ;
#ifdef DEBUG_FHEAP
    void printChildren ( unsigned int = 0 ) const ;
#endif

    ENT * getEntryData () { return _ent ; }
    const ENT * getEntryData () const { return _ent ; }

  } ;

  friend class Entry ;

private :

  typename RS_FHeap :: Entry * _min ;
  size_type _num ;
  mutable size_type _d_cal ;
  mutable size_type _num_d_cal ;

  vector < typename RS_FHeap :: Entry * > cvec ;

  size_type getD () const ;

  void putIntoRoot ( RS_FHeap :: Entry * ) ;
  void execConsolidate () ;

public :

  explicit RS_FHeap ()
    : _min ( 0 ) , _num ( 0 ) , _d_cal ( 0 ) , _num_d_cal ( 0 ) , cvec () {}

  Entry * getMinimum () const { return _min ; }

  void insert ( RS_FHeap :: Entry * ) ;
  Entry * deleteMinimum () ;

  size_type size () const { return _num ; }

} ;


// ----
// Some implementation of class Heap
// ヒープクラスの実装の一部
// ----

template < class KC , class ENT >
void
RS_FHeap < KC , ENT > :: putIntoRoot
( typename RS_FHeap < KC , ENT > :: Entry * _new )
{
#ifdef DEBUG_FHEAP
  cerr << "putIntoRoot: start, entry = " << * ( _new -> getEntryData () )
       << "(" << * ( _new -> getLeft () -> getEntryData () ) << " - "
       << * ( _new -> getEntryData () ) << " - "
       << * ( _new -> getRight () -> getEntryData () ) << ")"<< endl ;
#endif
  if ( _min )
  {
#ifdef DEBUG_FHEAP
    cerr << "putIntoRoot: _min = " << * ( _min -> getEntryData () )
       << "(" << * ( _min -> getLeft () -> getEntryData () ) << " - "
       << * ( _min -> getEntryData () ) << " - "
       << * ( _min -> getRight () -> getEntryData () ) << ")"<< endl ;
#endif
    _min -> _left -> _right = _new ;
    _new -> _left = _min -> _left ;
    _new -> _right = _min ;
    _min -> _left = _new ;
    if ( _new -> _key < _min -> _key )
    {
      _min = _new ;
    }
  }
  else
  {
#ifdef DEBUG_FHEAP
    cerr << "putIntoRoot: _min not found, heap size = " << _num << endl ;
#endif
    _min = _new ;
  }
#ifdef DEBUG_FHEAP
  cerr << "putIntoRoot: finished, entry = " << * ( _new -> getEntryData () )
       << "(" << * ( _new -> getLeft () -> getEntryData () ) << " - "
       << * ( _new -> getEntryData () ) << " - "
       << * ( _new -> getRight () -> getEntryData () ) << ")"<< endl ;
#endif
}



template < class KC , class ENT >
typename RS_FHeap < KC , ENT > :: size_type
RS_FHeap < KC , ENT > :: Entry :: countEntriesInMe
()
  const
{
  typename RS_FHeap :: size_type _retv = 1 ;
  if ( _child )
  {
    Entry * _csc = _child ;
    do
    {
      _retv += _csc -> countEntriesInMe () ;
      _csc = _csc -> _right ;
    }
    while ( _csc != _child ) ;
  }
  return _retv ;
}



template < class KC , class ENT >
void
RS_FHeap < KC , ENT > :: Entry :: cutFromChildList
()
{
#ifdef DEBUG_FHEAP
  cerr << "cut: object = " << * ( getEntryData () ) << "<"
       << getDegree () << ">, parent = "
       << * ( _parent -> getEntryData () ) << "<"
       << _parent -> getDegree () << ">" << endl ;
#endif
  -- ( _parent -> _deg ) ;
  _right -> _left = _left ;
  _left -> _right = _right ;
  if ( _parent -> _child == this )
  {
#ifdef DEBUG_FHEAP
    cerr << "cut: parent's child pointer points to this" << endl ;
#endif
    if ( this -> _right == this )
    {
#ifdef DEBUG_FHEAP
      cerr << "cut: no child must be present, degree actually = "
           << _parent -> getDegree () << endl ;
#endif
      _parent -> _child = 0 ;
    }
    else
    {
      _parent -> _child = _left ;
    }
  }
  _left = _right = this ;
  _parent = 0 ;
  _marked = false ;
  _myheap -> putIntoRoot ( this ) ;
}



#ifdef DEBUG_FHEAP
template < class KC , class ENT >
void
RS_FHeap < KC , ENT > :: Entry :: printChildren
( unsigned int _indent /* = 0 */ )
  const
{
  if ( _child )
  {
    Entry * _csc = _child ;
    do
    {
      for ( unsigned int i = 0 ; i < _indent ; ++ i )
      {
        cerr << "   " ;
      }
      cerr << "+--" << * ( _csc -> getEntryData () ) << "<"
           << _csc -> getDegree () << ">[" << _csc -> getKey () << "]("
           << _csc -> countEntriesInMe () << ")" << endl ;
      _csc -> printChildren ( _indent + 1 ) ;
      _csc = _csc -> _right ;
    }
    while ( _csc != _child ) ;
  }
}
#endif



template < class KC , class ENT >
void
RS_FHeap < KC , ENT > :: Entry :: execCascadingCut
()
{
  if ( _parent )
  {
#ifdef DEBUG_FHEAP
    cerr << "cascading cut: parent: " << * ( _parent -> getEntryData () ) << "["
         << _parent -> getKey () << "]" ;
    if ( _parent -> _marked )
      cerr << "[M]" ;
    cerr << endl ;
#endif
    if ( _parent -> _marked )
    {
#ifdef DEBUG_FHEAP
      cerr << "parent has been marked, cut from child list" << endl ;
#endif
      typename RS_FHeap < KC , ENT > :: Entry * px = _parent ;
      cutFromChildList () ;
      px -> execCascadingCut () ;
    }
    else
    {
#ifdef DEBUG_FHEAP
      cerr << "mark parent: " << * ( _parent -> getEntryData () ) << "["
           << _parent -> getKey () << "]" ;
      if ( _parent -> _marked )
        cerr << "[M]" ;
#endif
      _parent -> _marked = true ;
#ifdef DEBUG_FHEAP
      cerr << " -> " << * ( _parent -> getEntryData () ) << "["
           << _parent -> getKey () << "]" ;
      if ( _parent -> _marked )
        cerr << "[M]" ;
      cerr << endl ;
#endif
    }
  }
  else
  {
#ifdef DEBUG_FHEAP
    cerr << "cascading cut: no parent. done." << endl ;
#endif
  }
}


template < class KC , class ENT >
void
RS_FHeap < KC , ENT > :: Entry :: decreaseKey
( const KC & x )
{
  if ( _key < x )
  {
    cerr << "Error: Heap::Entry::decreaseKey(...): new key must be smaller "
         << "than the original key" << endl ;
    exit ( 1 ) ;
  }
  _key = x ;
#ifdef DEBUG_FHEAP
  cerr << "decreaseKey: key set" << endl ;
#endif
  if ( _parent )
  {
#ifdef DEBUG_FHEAP
    cerr << "parent exists" << endl ;
#endif
    if ( _key < _parent -> getKey () )
    {
#ifdef DEBUG_FHEAP
      cerr << "parent has larger key" << endl ;
#endif
      typename RS_FHeap < KC , ENT > :: Entry * px = _parent ;
#ifdef DEBUG_FHEAP
      cerr << "before cut" << endl ;
#endif
      cutFromChildList () ;
#ifdef DEBUG_FHEAP
      cerr << "before cascading cut" << endl ;
#endif
      px -> execCascadingCut () ;
#ifdef DEBUG_FHEAP
      cerr << "cut complete" << endl ;
#endif
    }
  }
  else
  {
#ifdef DEBUG_FHEAP
    cerr << "parent does not exist" << endl ;
#endif
  }
  if ( _myheap -> _min -> _key > x )
  {
#ifdef DEBUG_FHEAP
    cerr << "this is the minimum entry" << endl ;
#endif
    _myheap -> _min = this ;
  }
}


template < class KC , class ENT >
typename RS_FHeap < KC , ENT > :: Entry *
RS_FHeap < KC , ENT > :: deleteMinimum
()
{
  typename RS_FHeap < KC , ENT > :: Entry * ret_val = _min ;
#ifdef DEBUG_FHEAP
  cerr << "deleteMin starts, current heap size: " << _num << " elements"
       << endl ;
#endif
  while ( _min -> _child )
  {
#ifdef DEBUG_FHEAP
    cerr << "deleteMin: child found, _min = " << * ( _min -> getEntryData () )
         << endl ;
    typename RS_FHeap < KC , ENT > :: Entry * _mc
      = _min -> _child ;
    typename RS_FHeap < KC , ENT > :: Entry * _mp = _mc -> _parent ;
    cerr << "child: " << _mc -> getKey () << " [" << _mc -> getDegree ()
         << "]: " << * ( _mc -> getEntryData () ) << " ("
         << * ( _mc -> getLeft () -> getEntryData () )
         << " - " << * ( _mc -> getEntryData () ) << " - "
         << * ( _mc -> getRight () -> getEntryData () ) << ")" << endl ;
    cerr << "child's parent: " << _mp -> getKey () << " ["
         << _mp -> getDegree () << "]: " << * ( _mp -> getEntryData () )
         << " (" << * ( _mp -> getLeft () -> getEntryData () )
         << " - " << * ( _mp -> getEntryData () ) << " - "
         << * ( _mp -> getRight () -> getEntryData () ) << ")" << endl ;
#endif
    _min -> _child -> cutFromChildList () ;
  }
#ifdef DEBUG_FHEAP
  cerr << "deleteMin: no child list, _min = "
       << * ( _min -> getEntryData () ) << endl ;
#endif
  if ( ret_val -> _right == ret_val )
  {
#ifdef DEBUG_FHEAP
    cerr << "deleteMin: right of ret_val is ret_val: _num should be 1, "
         << "actually: " << _num << endl ;
#endif
    _min = 0 ;
  }
  else
  {
#ifdef DEBUG_FHEAP
    cerr << "deleteMin: set _min to _right of ret_val, "
         << * ( ret_val -> _right -> getEntryData () ) << endl ;
#endif
    _min = ret_val -> _right ;
    ret_val -> _right -> _left = ret_val -> _left ;
    ret_val -> _left -> _right = ret_val -> _right ;
    execConsolidate () ;
  }
  -- _num ;
#ifdef DEBUG_FHEAP
  if ( _min )
  {
    cerr << "deleteMin: root list" << endl ;
    typename RS_FHeap < KC , ENT > :: Entry * _nc = _min ;
    typename RS_FHeap < KC , ENT > :: size_type _cx = 0 ;
    do
    {
      cerr << * ( _nc -> getEntryData () ) << "<" << _nc -> getDegree ()
           << ">[" << _nc -> getKey () << "](" << _nc -> countEntriesInMe ()
           << ")" << endl ;
      _nc -> printChildren () ;
      _nc = _nc -> _right ;
      _cx += _nc -> countEntriesInMe () ;
    }
    while ( _nc != _min ) ;
    cerr << "_num, _num actually: " << _num << ", " << _cx << endl ;
  }
  else
  {
    cerr << "deleteMin: root list empty" << endl
         << "_num, _num actually: " << _num << ", 0" << endl ;
  }
#endif
  return ret_val ;
}


template < class KC , class ENT >
typename RS_FHeap < KC , ENT > :: size_type
RS_FHeap < KC , ENT > :: getD
()
  const
{
  if ( _num_d_cal == _num )
  {
    return _d_cal ;
  }
  _num_d_cal = _num ;
  double _dn = log ( _num ) / log ( ( 1 + sqrt ( 5 ) ) / 2 ) ;
  if ( _dn < 0 )
    _dn = 0 ;
  return ( _d_cal = static_cast < size_type > ( ceil ( _dn ) ) ) ;
}


template < class KC , class ENT >
void
RS_FHeap < KC , ENT > :: execConsolidate
()
{
#ifdef DEBUG_FHEAP
  cerr << "consolidation starts, getD: " << getD () << endl ;
#endif
  cvec . assign ( getD () , 0 ) ;
  typename RS_FHeap < KC , ENT > :: Entry * _nw = _min ;
  typename RS_FHeap < KC , ENT > :: Entry * _minx = _min ;
  do
  {
    _min = _minx ;
#ifdef DEBUG_FHEAP
    cerr << "check: " << _nw -> getKey () << " [" << _nw -> getDegree ()
         << "]: " << * ( _nw -> getEntryData () ) << " ("
         << * ( _nw -> getLeft () -> getEntryData () )
         << " - " << * ( _nw -> getEntryData () ) << " - "
         << * ( _nw -> getRight () -> getEntryData () ) << ")" << endl ;
#endif
    typename RS_FHeap < KC , ENT > :: Entry * _nx = _nw ;
    _nw = _nw -> _right ;
    while ( _nx -> _deg >= cvec . size () )
    {
      cerr << "Warning: degree vector not sufficient, deg, size ="
           << _nx -> _deg << ", " << cvec . size () << endl ;
      cvec . push_back ( 0 ) ;
    }
    size_type _d = _nx -> _deg ;
#ifdef DEBUG_FHEAP
    cerr << "_min degree: " << _d << endl ;
#endif
    if ( cvec [ _d ] == _nx )
    {
      cerr << "Warning: this degree checked, continue" << endl ;
      continue ;
    }
    while ( cvec [ _d ] )
    {
      typename RS_FHeap < KC , ENT > :: Entry * _ny = cvec [ _d ] ;
#ifdef DEBUG_FHEAP
      cerr << "degree " << _d << " already there, " ;
      cerr << _ny -> getKey () << " [" << _ny -> getDegree ()
           << "]: " << * ( _ny -> getEntryData () ) << " ("
           << * ( _ny -> getLeft () -> getEntryData () )
           << " - " << * ( _ny -> getEntryData () ) << " - "
           << * ( _ny -> getRight () -> getEntryData () ) << ")" << endl ;
#endif
      if ( _ny -> _key < _nx -> _key )
      {
        typename RS_FHeap < KC , ENT > :: Entry * _nz = _nx ;
        _nx = _ny ;
        _ny = _nz ;
#ifdef DEBUG_FHEAP
        cerr << "exchanged nx and ny, ny = " ;
        cerr << _ny -> getKey () << " [" << _ny -> getDegree ()
             << "]: " << * ( _ny -> getEntryData () ) << " ("
             << * ( _ny -> getLeft () -> getEntryData () )
             << " - " << * ( _ny -> getEntryData () ) << " - "
             << * ( _ny -> getRight () -> getEntryData () ) << ")" << endl ;
#endif
      }
      if ( _ny == _minx )
      {
        _minx = _minx -> _right ;
      }
#ifdef DEBUG_FHEAP
      cerr << "before addtochildlist, _nx: " << _nx -> getKey ()
           << " [" << _nx -> getDegree ()
           << "]: " << * ( _nx -> getEntryData () ) << " ("
           << * ( _nx -> getLeft () -> getEntryData () )
           << "<" << _nx -> getLeft () -> getDegree () << ">"
           << " - " << * ( _nx -> getEntryData () ) << " - "
           << * ( _nx -> getRight () -> getEntryData () )
           << "<" << _nx -> getRight () -> getDegree () << ">"
           << ")" ;
      if ( _nx -> _child )
      {
        cerr << " (child: " ;
        string x_str = "" ;
        typename RS_FHeap < KC , ENT > :: Entry * _nc = _nx -> _child ;
        do
        {
          cerr << x_str << * ( _nc -> getEntryData () )
               << "<" << _nc -> getDegree () << ">" ;
          x_str = " - " ;
          _nc = _nc -> _right ;
        }
        while ( _nc != _nx -> _child ) ;
        cerr << ")" ;
      }
      cerr << endl ;
#endif
      _ny -> _right -> _left = _ny -> _left ;
      _ny -> _left -> _right = _ny -> _right ;
      _ny -> _right = _ny -> _left = _ny ;
      _nx -> addToChildList ( _ny ) ;
#ifdef DEBUG_FHEAP
      cerr << "after addtochildlist, _nx: " << _nx -> getKey ()
           << " [" << _nx -> getDegree ()
           << "]: " << * ( _nx -> getEntryData () ) << " ("
           << * ( _nx -> getLeft () -> getEntryData () )
           << "<" << _nx -> getLeft () -> getDegree () << ">"
           << " - " << * ( _nx -> getEntryData () ) << " - "
           << * ( _nx -> getRight () -> getEntryData () )
           << "<" << _nx -> getRight () -> getDegree () << ">"
           << ")" ;
      if ( _nx -> _child )
      {
        cerr << " (child: " ;
        string x_str = "" ;
        typename RS_FHeap < KC , ENT > :: Entry * _nc = _nx -> _child ;
        do
        {
          cerr << x_str << * ( _nc -> getEntryData () )
               << "<" << _nc -> getDegree () << ">" ;
          x_str = " - " ;
          _nc = _nc -> _right ;
        }
        while ( _nc != _nx -> _child ) ;
        cerr << ")" ;
      }
      cerr << endl ;
#endif
      cvec [ _d ] = 0 ;
      ++ _d ;
    }
#ifdef DEBUG_FHEAP
    cerr << "degree " << _d << ": this one" << endl ;
#endif
    cvec [ _d ] = _nx ;
  }
  while ( _nw != _min ) ;
  _min = 0 ;
#ifdef DEBUG_FHEAP
  cerr << "before search, _min set to Null" << endl ;
#endif
  for ( vector < size_type > :: size_type i = 0 ; i < cvec . size () ; ++ i )
  {
#ifdef DEBUG_FHEAP
    cerr << "degree " << i << " scanning" << endl ;
#endif
    if ( cvec [ i ] )
    {
#ifdef DEBUG_FHEAP
      cerr << "degree " << i << " found: "
           << * ( cvec [ i ] -> getEntryData () ) << "["
           << cvec [ i ] -> getKey () << "]" << endl ;
#endif
      if ( ! _min || cvec [ i ] -> _key < _min -> _key )
      {
#ifdef DEBUG_FHEAP
        cerr << " ... this is the new minimum" << endl ;
#endif
        _min = cvec [ i ] ;
      }
    }
  }
#ifdef DEBUG_FHEAP
  cerr << "end: " << _min -> getKey () << " [" << _min -> getDegree ()
       << "]: " << * ( _min -> getEntryData () ) << " ("
       << * ( _min -> getLeft () -> getEntryData () )
       << " - " << * ( _min -> getEntryData () ) << " - "
       << * ( _min -> getRight () -> getEntryData () ) << ")" << endl ;
  cerr << "consolidation ended" << endl ;
#endif
}



template < class KC , class ENT >
void
RS_FHeap < KC , ENT > :: insert
( RS_FHeap < KC , ENT > :: Entry * _in )
{
  putIntoRoot ( _in ) ;
  ++ _num ;
}



template < class KC , class ENT >
void
RS_FHeap < KC , ENT > :: Entry :: addToChildList
( typename RS_FHeap < KC , ENT > :: Entry * _in )
{
  if ( _child )
  {
    _child -> _left -> _right = _in ;
    _in -> _left = _child -> _left ;
    _child -> _left = _in ;
    _in -> _right = _child ;
  }
  else
  {
    _child = _in ;
  }
  _in -> _parent = this ;
  ++ _deg ;
}




#endif // RS_FHEAP_H
2019 年 9月 »
9月
1234567
891011121314
15161718192021
22232425262728
2930