18:ハッシュを使って高速探索
前回で特定のオブジェクトを探索する方法を紹介しましたが、頻繁に呼び出しが必要なオブジェクトをリストから逐一線形探索をしていたのであれば、その負荷は非常に大きなものになります。そこで、専用の「箱」に入れておくことで、特定のオブジェクトをすぐに取り出せるようにしましょう。Visual C++をはじめとする一部のC++開発環境では「hash_map(もしくはunordered_map)」というクラスが用意されています。mapクラスとの大きな違いはキー名を元に探索するためのアルゴリズムの違いにあります。mapは二分木探索であるのに対し、hash_mapはハッシュアルゴリズムによって検索されます。この差は大変大きなもので、時にはhash_mapの方が2倍近く高速になることもあります。そのため、今回はhash_mapを使って解説しますが、利用できる関数は共通ですので、お使いの開発環境が対応していないようであれば、hash_mapをmapに置き換えてご覧下さい。
hash_mapはSTLの概念には沿っているものの、STL標準ではないため、宣言方法は開発環境によってまちまちです。なお、Visual C++の場合は以下のように記述します。ここでSTLの文字列管理クラス「string」も併せて宣言されていますが、その理由は後ほど紹介。
#include <string>
using namespace std;
#include <hash_map>
using namespace stdext;
class CGameObject
{
private:
// アイテムボックスの宣言
static hash_map<string, CGameObject*> itembox;
class CGameObject
{
public:
// オブジェクトを格納
static void AppendItemBox(LPCSTR name, CGameObject *object);
// 指定したキーに格納されているオブジェクトを取り除く
// (実際に削除する場合はRemoveObject()を使うこと!)
static void RemoveItemBox(LPCSTR name);
// アイテムボックス内のデータをすべて取り除く
static void ResetItemBox();
// 指定した文字列に対応するオブジェクトを取得する
static CGameObject* FindItemBox(LPCSTR name);
void CGameObject::AppendItemBox(LPCSTR name, CGameObject *object)
{
itembox.insert(make_pair(name, object));
}
void CGameObject::RemoveItemBox(LPCSTR name)
{
itembox.erase(name);
}
void CGameObject::ResetItemBox()
{
itembox.clear();
}
CGameObject* CGameObject::FindItemBox(LPCSTR name)
{
hash_map<string, CGameObject*>::iterator i;
i = itembox.find(name);
if(i == itembox.end()) return NULL;
return i->second;
}