hayasi リファレンス

written by Shinsuke Okazaki

ホームページ:http://natsuhaze.jp/software/

 

hayasiとは、ハッシュデータを実現する、vectorもどきを使用したクラスです。(ハヤシライスから命名)

ハッシュデータは、データを散らして(ハッシュ)、高速性を高めており、vectorに比べると、データの挿入、削除の処理時間が向上しています(詳しくは専門書をお読みください。私は厳密なことは相当前に学んで文献も手元にないのでわかりません) 。データのアクセススピードはvectorより劣りますが、ハッシュサイズを大きくすることで高速化することもできます。

 

hayasiに限って言えば、その正体はvectorを使った、ソートされている2次元配列です。1次元目はハッシュ関数と言われる関数が与えるハッシュ値がインデックスになっており、2次元目は同じハッシュ値(1次元目の配列のインデックス)になってしまったデータをキー値(これはユーザが設定する一意な値)を元にソートして格納しています。

 

ハッシュは、ハッシュ関数の性能と、ハッシュサイズの大きさによって処理速度が変化します。ハッシュサイズが大きければ大きいほど(つまりhayasiなら1次元目の配列が大きければ大きいほど)、アクセスするスピードは配列と近くなります。逆にハッシュサイズが小さいほど同じハッシュ値(要するにhayasiでいう1次元目の配列のインデックス)になるデータが多くなり、スピードが遅くなります。hayasiでは、ハッシュサイズが少なく同じハッシュ値になりやすい状況でも高速にアクセスできるよう、同じハッシュ値のデータはソートするようにしてあります。ソートしたデータはバイナリサーチで高速に検索しています。

 

またハッシュ値が大きいとデータの挿入時間、削除時間が早くなります。

 

hayasiはSTLのmapの代替として使うように作りましたので、mapと同じような使い方を想定していると見てもかまいません。

 

クラス宣言

template<class T,class KEY_T, class CompareClass =NV_DefaultHayasiCompareClass<KEY_T> > class hayasi

T:格納するデータタイプ

KEY_T:キーとなる型 

CompareClass:比較クラス

KEY_Tは配列で言うところのインデックスの型を指定します。基本は整数型ですが、文字列でも何でもかまいません。しかし、デフォルトの比較クラスは使用できませんので自作する必要があります。(hayasi_test2.cpp参照)

コンストラクタ

hayasi(int new_hash_sizel = HAYASI_DEFAULT_HASH_VALUE ,int inc_val=0 )

new_hash_sizel :ハッシュサイズ

inc_val:重複したキー値のメモリ確保時の増分個数。0だとデフォルト値(8)

inc_valはデフォルトのゼロのままだと、データがないところをあらかじめメモリ割り当てしてしまうので、省メモリを考慮するなら何らかの値を入れてください。

データの初期化

int init(int new_hash_size,int inc_val=0){

new_hash_sizel :ハッシュサイズ

inc_val:重複したキー値のメモリ確保時の増分個数。0だとデフォルト値(8)

コンストラクタはinit()を呼び出しているだけです。またclear()でデータをすべて削除したときに再度使用するときはinit()を使用してください。hayasi.hを見ればわかりますが、clear()を実行しなくてもinit()で前のデータは全クリアします。

データの挿入

int set(const KEY_T &key, const T &obj)

 

key:キー値

obj:データ

 

返り値: 1:成功 0:失敗

 

この関数は一度に大量のデータを代入するときに使用してください。

キー値は、必ず一意な(ユニークな)値にしてください。

 

データの検索

const T* get(const KEY_T &key)


key:キー値

返り値:検索したデータ。NULLの場合は検索したデータがない

 

データの削除

int remove(const KEY_T &key){

key:キー値

返り値: 1:成功 0:失敗

成功すると、その後指定したキー値で検索すると失敗します。remove()はキー値とそれに関連づけられたデータを完全に内部で消去します。

データの列挙

int enumerate(int &i,int &j,T *obj, KEY_T *key){

i,j:最初0にして呼び出してください。その後は関数が0を返すまで値を変化させないでください。

    (サンプルコードは、hayasi_test2.cpp参照)

obj:取り出したデータ

key:取り出したキー値

返り値: 1:成功 0:データ列挙終了

 

データのクリア

void clear()

全データをクリアします。

[]のオーバーロード:データの取り出しと代入

T& operator[](const KEY_T &key)

key:新たに設定する、またはデータを取り出すキー値

これはhayasiを配列変数のように使えるために設けたものです。

データの代入にも使用できますが、仕様上、速度が遅いのでできるだけset()を使用してください。

(1つのデータだけを追加したい場合はこちらの方が早いです)

 

これを使用すると見た目が配列のように見えますが、若干配列とは挙動が違います。

keyがhayasiの中に存在しない場合、新たにデータを作成してそれを返します。

(データがクラスオブジェクトなら、デフォルトのコンストラクタで指定したデータになります)

 

したがって、以下のような使い方をするとデータの内容が不定になりますので注意してください。

 

data = hayasi_data[new_key]; //new_keyはhayasi_dataの中で今まで存在しないキー

 

具体例はhayasi_test2.cppを参照してください。

hayasiのファイル入出力について

enumerate()で取り出しして、セーブし、ロードはset()でやればできますが、見た目が汚くなりますので、ファイル入出力クラスだけhayasiの全データをフルアクセスできるfriend宣言をして、ファイル入出力クラスにhayasiやvectorの専用の入出力関数を記述すると見た目がすっきりします。もちろんその関数をテンプレート関数にすれば汎用的なものとなります。(FileIO.hのhfio()参照)