株式会社エス・スリー・フォー

STLport のハッシュ・コンテナ


C++vector, list, deque, set, multiset, map, multimap 7  vector, list, deque  O(N), set, multiset, map, multimap  O(logN) 

(hashtable) O(1) C++()

SGI(Silicon Graphics)STLSTLport(http://www.stlport.org)C++ hash_set, hash_multiset, hash_map, hash_multimap 

 hash_set  hash_map (hash_multiset, hash_multimap )


hash_set (stlport/stl/_hash_set.h )

template <class Key, class HashFcn =hash<Key>, class EqualKey =equal_to<Key>,
          class Alloc =allocator<Key> >
class hash_set {
public:
  typedef ... key_type;
  typedef ... value_type;
  typedef ... hasher;
  typedef ... key_equal;

  typedef ... size_type;
  typedef ... difference_type;
  typedef ... pointer;
  typedef ... const_pointer;
  typedef ... reference;
  typedef ... const_reference;

  typedef ...            const_iterator;
  typedef const_iterator iterator;

  typedef ... allocator_type;

  hasher hash_funct() const;
  key_equal key_eq() const;
  allocator_type get_allocator() const;

  hash_set();
  explicit hash_set(size_type);
  hash_set(size_type, const hasher&);
  hash_set(size_type, const hasher&, const key_equal&, const allocator_type& =allocator_type());

  template <class InputIterator>
  hash_set(InputIterator, InputIterator);

  template <class InputIterator>
  hash_set(InputIterator, InputIterator, size_type );

  template <class InputIterator>
  hash_set(InputIterator, InputIterator, size_type, const hasher&);

  template <class InputIterator>
  hash_set(InputIterator, InputIterator, size_type, const hasher&, const key_equal&);

  template <class InputIterator>
  hash_set(InputIterator, InputIterator, size_type, const hasher&, const key_equal&, const allocator_type&);

  size_type size() const;
  size_type max_size() const;
  bool empty() const;
  void swap(hash_set&);

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

  pair<iterator, bool> insert(const value_type&);

  template <class InputIterator>
  void insert(InputIterator, InputIterator); 

  pair<iterator, bool> insert_noresize(const value_type&);

  template <class KT>
  iterator find(const KT&) const;

  size_type count(const key_type&) const;
  pair<iterator, iterator> equal_range(const key_type&) const;

  size_type erase(const key_type&);
  void erase(iterator);
  void erase(iterator, iterator);
  void clear();

  void resize(size_type);
  size_type bucket_count() const;
  size_type max_bucket_count() const;
  size_type elems_in_bucket(size_type) const;

};


hash_map (stlport/stl/_hash_map.h )

template <class Key, class Data, class HashFcn =hash<Key>, class EqualKey =equal_to<_Key>,
          class Alloc =allocator< pair<const Key,Data> > >
class hash_map {
public:
  typedef ... key_type;
  typedef ... data_type;
  typedef ... mapped_type;
  typedef ... value_type;
  typedef ... hasher;
  typedef ... key_equal;
  
  typedef ... size_type;
  typedef ... difference_type;
  typedef ... pointer;
  typedef ... const_pointer;
  typedef ... reference;
  typedef ... const_reference;

  typedef ... iterator;
  typedef ... const_iterator;

  typedef ... allocator_type;

  hasher hash_funct() const;
  key_equal key_eq() const;
  allocator_type get_allocator() const;

  hash_map();
  explicit hash_map(size_type);
  hash_map(size_type, const hasher&);
  hash_map(size_type, const hasher&, const key_equal&, const allocator_type& =allocator_type());

  template <class InputIterator>
  hash_map(InputIterator, InputIterator);

  template <class InputIterator>
  hash_map(InputIterator, InputIterator, size_type);

  template <class InputIterator>
  hash_map(InputIterator, InputIterator, size_type, const hasher&);

  template <class InputIterator>
  hash_map(InputIterator, InputIterator, size_type, const hasher&, const key_equal&)

  template <class InputIterator>
  hash_map(InputIterator, InputIterator, size_type, const hasher&, const key_equal&, 
            const allocator_type& =allocator_type());

  size_type size() const;
  size_type max_size() const;
  bool empty() const;
  void swap(hash_map&);
  iterator begin();
  iterator end();
  const_iterator begin() const;
  const_iterator end() const;

  pair<iterator,bool> insert(const value_type&);

  template <class InputIterator>
  void insert(InputIterator, InputIterator);

  pair<iterator,bool> insert_noresize(const value_type&)

  iterator find(const key_type&);
  const_iterator find(const key_type&) cons;

  Data& operator[](const key_type&);

  size_type count(const key_type& __key) const;
  
  pair<iterator, iterator> equal_range(const key_type&);

  pair<const_iterator, const_iterator> equal_range(const key_type&) const;

  size_type erase(const key_type&);
  void erase(iterator);
  void erase(iterator, iterator);
  void clear();

  void resize(size_type);
  size_type bucket_count() const;
  size_type max_bucket_count() const;
  size_type elems_in_bucket(size_type) const;

};



template :Key:HashFcn:EqualKey:Alloc

:HashFcn Key size_t 

STLport 使:


char*

const char*

crope

wrope

char

singned char

undigned char

short

unsigned short

int

unsigned int

long

unsigned long

string

wstring


:hash<T>

:EqualKey  std::equal_to<Key> HashFcnoperator== 

example

struct person {
  std::string name;
  int         age;
};

struct person_hash {
  std::hash<string> hs;
  std::hash<int>    hi;
  size_t operator()(const person&x) const {
    return static_cast<size_t>(hs(x.name) & hi(x.age));
  }
};

struct person_equal {
  bool operator()(const person& x, const person&y) const {
    return x.name == y.name && x.age == y.age;
  }
};

std::hash_set<person, person_hash, person_equal> person_set;
...

bucket


STLportbucketbucket bucket_count() bucket'bucket'

bucketbucket

bucket(bucket elems_in_bucket() )bucket

bucketbucketbucketbucketbucket resize() bucketbucket insert_noresize() 

1,000,000hash_setbucket調

bucket_count.cpp

#include <iostream>
#include <iomanip>
#include <hash_set>

int main() {
  std::hash_set<int> hs;
  std::hash_set<int>::size_type buckets = hs.bucket_count();

  std::cout << std::setw(7) << hs.size() << '\t' 
            << std::setw(7) << buckets << std::endl;
  const int N = 100000;
  for ( int i = 1; i <= N; ++i ) {
    hs.insert(i);
    if ( buckets != hs.bucket_count() ) {
      buckets = hs.bucket_count();
      std::cout << std::setw(7) << hs.size() << '\t' 
                << std::setw(7) << buckets << std::endl;
    }
  }
  return 0;
}

      0     193
    194     389
    390     769
    770    1543
   1544    3079
   3080    6151
   6152   12289
  12290   24593
  24594   49157
  49158   98317
  98318  196613

iterator


iteratoriterator(operator++)(operator)

hash_setiterator const_iterator 

ハッシュは本当に速いのか?


C++
set/map(multiset/multimap)(binary-tree)//



C++



3:



Dinkum Standard Library 2.33 (Dinkumware)
Visual C++OEMSTL



STLport 4.5.1 (STLport)
SGIOS/使



SourcePro/Core (Rogue Wave)
C++ BuilderOEMSTL



Windows2000,Visual C++6.0/DLL
#include <windows.h> // GetTickCount
#include <iostream>  // cout
#include <set>       // set

#if   defined(BENCH_DINKUM)
#include <hash_set>

typedef std::hash_set<int> hashset_type;

#elif defined(BENCH_STLPORT)
#include <hash_set>

typedef std::hash_set<int> hashset_type;

#elif defined(BENCH_SOURCEPRO)
#include <rw/stdex/hashset.h>
struct inthash {
  unsigned long operator()(int x) const { return x; }
};

typedef rw_hashset<int,inthash,std::equal_to<int>,std::allocator<int> > hashset_type;

#endif

template<class C>
void bench(const char* msg, C& c, size_t N) {
  std::cout << msg << '(' << N <&lt ')';
  int i;
  long tick = GetTickCount();
  for ( i = 0; i < N; ++i )
    c.insert(i);
  for ( i = 0; i < N; ++i )
    c.erase(i);
  tick = GetTickCount() - tick;
  std::cout << tick << "[ms], " << (double)tick/(double)N << "[ms/element]" << std::endl;
}

int main() {
  for ( size_t n = 1000; n < 40000; n += n ) {
    hashset_type hs;
    bench("hash table", hs, n);
    std::set<int> s;
    bench("bin.  tree", s, n);
  }
  return 0;
}

benchint[0,N)N/1

main 1000, 2000, 4000,  32000bench

Dinkum

ash table(1000)10[ms], 0.01[ms/element]
bin.  tree(1000)10[ms], 0.01[ms/element]
hash table(2000)30[ms], 0.015[ms/element]
bin.  tree(2000)10[ms], 0.005[ms/element]
hash table(4000)100[ms], 0.025[ms/element]
bin.  tree(4000)20[ms], 0.005[ms/element]
hash table(8000)371[ms], 0.046375[ms/element]
bin.  tree(8000)50[ms], 0.00625[ms/element]
hash table(16000)1422[ms], 0.088875[ms/element]
bin.  tree(16000)120[ms], 0.0075[ms/element]
hash table(32000)5658[ms], 0.176813[ms/element]
bin.  tree(32000)241[ms], 0.00753125[ms/element]

''

STLport

hash table(1000)0[ms], 0[ms/element]
bin.  tree(1000)10[ms], 0.01[ms/element]
hash table(2000)0[ms], 0[ms/element]
bin.  tree(2000)0[ms], 0[ms/element]
hash table(4000)0[ms], 0[ms/element]
bin.  tree(4000)20[ms], 0.005[ms/element]
hash table(8000)20[ms], 0.0025[ms/element]
bin.  tree(8000)30[ms], 0.00375[ms/element]
hash table(16000)20[ms], 0.00125[ms/element]
bin.  tree(16000)80[ms], 0.005[ms/element]
hash table(32000)50[ms], 0.0015625[ms/element]
bin.  tree(32000)171[ms], 0.00534375[ms/element]

5

SourcePro/Core

hash table(1000)11[ms], 0.011[ms/element]
bin.  tree(1000)10[ms], 0.01[ms/element]
hash table(2000)10[ms], 0.005[ms/element]
bin.  tree(2000)10[ms], 0.005[ms/element]
hash table(4000)20[ms], 0.005[ms/element]
bin.  tree(4000)20[ms], 0.005[ms/element]
hash table(8000)60[ms], 0.0075[ms/element]
bin.  tree(8000)40[ms], 0.005[ms/element]
hash table(16000)160[ms], 0.01[ms/element]
bin.  tree(16000)90[ms], 0.005625[ms/element]
hash table(32000)411[ms], 0.0128437[ms/element]
bin.  tree(32000)190[ms], 0.0059375[ms/element]

Dinkum

?




8string:
#include <windows.h>  // GetTickCount
#include<iostream>  // cout
#include <set>       // set
#include <vector>    // vector
#include <string>    // string

#if   defined(BENCH_DINKUM)
#include 

class str_hash {
public:
  enum {bucket_size = 4,
        min_buckets = 8};
  size_t operator()(const std::string&x) const {
    size_t result = 0;
    for ( int i = 0; i < x.size(); ++i )
      result = result * 5 + x[i];
    return result;
  }
  bool operator()(const std::string& x, const std::string&y) const
   { return x < y; }
};

typedef std::hash_set<std::string, str_hash> hashset_type;

#elif defined(BENCH_STLPORT)
#include <hash_set>

typedef std::hash_set<std::string> hashset_type;

#elif defined(BENCH_SOURCEPRO)
#include <rw/stdex/hashset.h>
struct strhash {
  unsigned long operator()(const std::string&x) const { 
    unsigned long result = 0;
    for ( int i = 0; i < x.size(); ++i )
      result = result * 5 + x[i];
    return result;
  }
};

typedef rw_hashset<std::string,strhash,std::equal_to<std::string>,
                   std::allocator<std::string> > hashset_type;

#endif

template
void bench(const char* msg, C& c, size_t N) {
  std::cout <&lt; msg <&lt; '(' <&lt; N >&gt; ')';
  int i;
  std::vector<std::string> data;
  for ( i = 0; i < N; ++i ) {
    char str_val[6];
    sprintf(str_val,"%08d",i);
    data.push_back(str_val);
  }
  long tick = GetTickCount();
  for ( i = 0; i < N; ++i )
    c.insert(data[i]);
  for ( i = 0; i < N; ++i )
    c.erase(data[i]);
  tick = GetTickCount() - tick;
  std::cout << tick << "[ms], " << (double)tick/(double)N << "[ms/element]" << std::endl;
}

int main() {
  for ( size_t n = 1000; n < 40000; n += n ) {
    hashset_type hs;
    bench("hash table", hs, n);
    std::set<std::string> s;
    bench("bin.  tree", s, n);
  }
  return 0;
}




Dinkum

hash table(1000)10[ms], 0.01[ms/element]
bin.  tree(1000)10[ms], 0.01[ms/element]
hash table(2000)40[ms], 0.02[ms/element]
bin.  tree(2000)20[ms], 0.01[ms/element]
hash table(4000)161[ms], 0.04025[ms/element]
bin.  tree(4000)50[ms], 0.0125[ms/element]
hash table(8000)370[ms], 0.04625[ms/element]
bin.  tree(8000)111[ms], 0.013875[ms/element]
hash table(16000)1902[ms], 0.118875[ms/element]
bin.  tree(16000)230[ms], 0.014375[ms/element]
hash table(32000)2714[ms], 0.0848125[ms/element]
bin.  tree(32000)490[ms], 0.0153125[ms/element]


STLport

hash table(1000)0[ms], 0[ms/element]
bin.  tree(1000)10[ms], 0.01[ms/element]
hash table(2000)0[ms], 0[ms/element]
bin.  tree(2000)20[ms], 0.01[ms/element]
hash table(4000)10[ms], 0.0025[ms/element]
bin.  tree(4000)50[ms], 0.0125[ms/element]
hash table(8000)31[ms], 0.003875[ms/element]
bin.  tree(8000)100[ms], 0.0125[ms/element]
hash table(16000)80[ms], 0.005[ms/element]
bin.  tree(16000)220[ms], 0.01375[ms/element]
hash table(32000)171[ms], 0.00534375[ms/element]
bin.  tree(32000)481[ms], 0.0150312[ms/element]


SourcePro/Core

hash table(1000)10[ms], 0.01[ms/element]
bin.  tree(1000)10[ms], 0.01[ms/element]
hash table(2000)20[ms], 0.01[ms/element]
bin.  tree(2000)30[ms], 0.015[ms/element]
hash table(4000)50[ms], 0.0125[ms/element]
bin.  tree(4000)60[ms], 0.015[ms/element]
hash table(8000)100[ms], 0.0125[ms/element]
bin.  tree(8000)130[ms], 0.01625[ms/element]
hash table(16000)240[ms], 0.015[ms/element]
bin.  tree(16000)271[ms], 0.0169375[ms/element]
hash table(32000)621[ms], 0.0194063[ms/element]
bin.  tree(32000)571[ms], 0.0178437[ms/element]



int