std::map を用いてハッシュ関数を実装する、事例が「ロベールのC++入門」という本に掲
載されています
setting[0101] = 元旦;
掲載されている事例では、Hash クラスのVALUE& operator[](const KEY& key)をオーバー
ライドさせ、
std::string 型のデータがstd::map に挿入される仕組みになっており
std::cout setting[0101] << std::endl;
このようにすればキー値に紐付けられた値が取り出せれます。
このプログラムを、後で日付データが利用したいため、下記のようにvector コンテナを
用いて実装しました。
typedef Hash<string, string> Setting;
vector<string> v;
Setting setting;
v.push_back(0101);
setting[v[0]] = 元旦;
ここからが質問なのですが、
vector コンテナを用いずにmap のイテレータを利用して日付データ(キー値)を走査し
たり扱いたいのですが、イテレータを付加しbegin() end() が使えるようにするには、ど
の様にしたら良いでしょうか。
# HashFn.h
#ifndef HASHFN_H_
#define HASHFN_H_
#include <string>
#include <cstddef>
// デフォルトのハッシュ関数
template <typename TYPE>
class HashFn
{
public:
static size_t Get(const TYPE& value);
static const size_t SIZE = 23; // ハッシュ表のサイズ
};
template<>
size_t HashFn<std::string>::Get(const std::string &value)
{
size_t size = value.size();
const unsigned char* p =
reinterpret_cast<const unsigned char*>(value.data());
return (p[0] + p[size / 2] + p[size - 1]) % SIZE;
}
#endif // #ifndef HASHFN_H_
# Hash.h
#ifndef HASH_H_
#define HASH_H_
#include HashFn.h
#include <map>
#include <stdexcept>
template <
typename KEY, // キーの型
typename VALUE, // 扱う値の型
typename HASH_FN = HashFn<KEY> // ハッシュ関数
>
class Hash
{
private:
typedef std::map<KEY, VALUE> Map;
typedef typename Map::const_iterator CIterator;
public:
VALUE& operator[](const KEY& key) {
size_t hashValue = HASH_FN::Get(key);
return m_hashTable[hashValue][key];
}
const VALUE& operator[](const KEY& key) const {
size_t hashValue = HASH_FN::Get(key);
const Map& map = m_hashTable[hashValue];
CIterator it = map.find(key);
if(it == map.end()) {
throw std::out_of_range(見つかりませんでした);
}
return it->second;
}
private:
Map m_hashTable[HASH_FN::SIZE];
};
#endif // #ifndef HASH_H_
# Hash1.cpp
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include Hash.h
using namespace std;
typedef Hash<string, string> Setting;
vector<string> v;
int main()
{
Setting setting;
v.push_back(0101);
v.push_back(0211);
v.push_back(0429);
v.push_back(0503);
v.push_back(0504);
v.push_back(0505);
v.push_back(1103);
v.push_back(1123);
v.push_back(1223);
// 固定祭日処理
setting[v[0]] = 元旦;
setting[v[1]] = 建国記念の日;
setting[v[2]] = 昭和の日;
setting[v[3]] = 憲法記念日;
setting[v[4]] = みどりの日;
setting[v[5]] = 子供の日;
setting[v[6]] = 文化の日;
setting[v[7]] = 勤労感謝の日;
setting[v[8]] = 天皇誕生日;
vector<string>::iterator it;
for(it = v.begin(); it < v.end(); it++)
cout << setting[*it] << endl;
return 0;
}
確認ですが、きょうびの標準C++ライブラリには
ハッシュ表:unordered_set/multiset/map/multimapが提供されてるのは
百も承知での質問でしょうか?
// VC++10 で動作確認
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
using namespace std;
int main() {
unordered_map<string,string> setting;
setting[0101] = 元旦;
setting[0211] = 建国記念の日;
setting[0429] = 昭和の日;
setting[0503] = 憲法記念日;
setting[0504] = みどりの日;
setting[0505] = 子供の日;
setting[1103] = 文化の日;
setting[1123] = 勤労感謝の日;
setting[1223] = 天皇誕生日;
for_each(setting.begin(), setting.end(),
[](const unordered_map<string,string>::value_type& item)
{ cout << item.first << ':' << item.second << endl; });
}
επιστημη さんお世話になります。
>>ハッシュ表:unordered_set/multiset/map/multimap ?
C++0x というやつですね、知りませんでした・・・というか、あなたの出筆された、
「C++テンプレートテクニック」のp324 に書いてありますね、よく読んでいませんでした。
環境を書き忘れていましたが、VC8 なので、この関数は使えないので
VC10 をインストルして、試したところ動作が確認できました、後でg++ でも試してみた
いと思います。
VC8 だと面倒なコードになるんでしょうね、「C++テンプレートテクニック」のSFINAE の
ところを真似て、begin()、end() を実装しようとしたのですが、理解力といいますか、
応用力が無くて頓挫しました。
VC8でならBoost使ってはいかがでしょうか。
http://www.boost.org/doc/libs/1_43_0/doc/html/boost_tr1/subject_list.html#boost
_tr1.subject_list.unordered_map
επιστημη さん
ありがとうございました。
VC++9なら(標準じゃないけど)hash_set/hash_mapなんてのも入ってますな。