ライブラリとして使われているkhash.h
を調べる。
C言語用のハッシュテーブルライブラリ。
ヘッダファイルkhash.h
をインクルードするだけで利用できる。
マクロが多用してありその点、気をつけないとこける。
ハッシュテーブルに名前をつけ他のハッシュテーブルと区別する。
ハッシュテーブルの要素はバケット(bucket)と呼ばれている。
このバケットにvalueを入れていく。バケットにアクセスするには
イーサレータでおこなう。データの追加時の衝突対策をどうやって
いるのかはよくわからない。
ハッシュテーブルにはmap型とset型があるが違いがよくわからない
主にmap型を使用している。
コード例
An example:(khash.hにあるコード例)
#include "khash.h"
KHASH_MAP_INIT_INT(32, char) //ここでハッシュテーブルに'32'という名前を付けている。charはハッシュテーブルのデータ(value)型を指定
int main() {
int ret, is_missing;
khiter_t k; //ハッシュテーブルのバスケット(bucket)にアクセスするためのイーサレータ
khash_t(32) *h = kh_init(32); //hはハッシュテーブルへのポインタ
//kh_putが指定されたハッシュテーブルの任意のkeyに対してバスケットを作成する(この時点ではvalueは入っていない)
//ret変数にはkeyがすでにハッシュテーブルに存在する場合は0、存在しない場合は1。この値でユーザー側が衝突対策をするのかな?
k = kh_put(32, h, 5, &ret);
kh_value(h, k) = 10; //ハッシュテーブルへのポインタ(h)とイーサレータ(k)で指定したバスケットにvalueを代入する
//代入文ではなくprintf("bucket=%d\n",kh_value(h, k))とするとバスケットにvalueがあればそれを返してくる。
k = kh_get(32, h, 10); //指定したハッシュテーブル・ポイントの指定したkey(ここでは10)に対応するバスケットがあればそのイーサレータを返す
//なければ特別なイーサレータkh_end(h)を返すのでkeyに対応したバスケットはないことがわかる。次の文がそれを判定している。
is_missing = (k == kh_end(h));
k = kh_get(32, h, 5);
kh_del(32, h, k); //イーサレータ(k)に対応したバスケットを削除
for (k = kh_begin(h); k != kh_end(h); ++k) //イーサレータをスキャンすることでハッシュテーブルを舐めることができる
if (kh_exist(h, k)) kh_value(h, k) = 1; //kh_exist関数はイーサレータにデータがあれば1なければ0
kh_destroy(32, h); //ハッシュテーブルの破壊
return 0;
}
ハッシュテーブルの生成
//整数キーを持つセット型ハッシュテーブルを作る
KHASH_SET_INIT_INT(name)->KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
//整数キーを持つマップ型ハッシュテーブルを作る
KHASH_MAP_INIT_INT(name, khval_t)->KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
//整数キー(64bit)を持つセット型ハッシュテーブルを作る
KHASH_SET_INIT_INT64(name)->KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
//整数キー(64bit)を持つマップ型ハッシュテーブルを作る
KHASH_MAP_INIT_INT64(name, khval_t)->KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)
//文字列キーを持つセット型ハッシュテーブルを作る
KHASH_SET_INIT_STR(name)->KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
//文字列キーを持つマップ型ハッシュテーブルを作る
KHASH_MAP_INIT_STR(name, khval_t)->KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
ハッシュテーブルの操作
整数キー同士が同じか判定する
kh_int_hash_equal(a,b) #整数キーの同一判定をする
kh_int64_hash_equal(a,b) #整数キー(64bit)の同一判定をする
与えられた整数キーをハッシュテーブルのindexにする関数
kh_int_hash_func(key) #32bit
kh_int64_hash_func(key) #64bit->32bitのインデックスに変換する
与えられた文字列キーをハッシュテーブルのindexにする関数
kh_str_hash_func(key)
文字列キー同士が同じか判定する
kh_str_hash_equal(a,b)
名前を与えられたハッシュテーブルの初期化とインスタンス変数
khash_t, kh_init
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
ハッシュテーブルのリセット
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
..
kh_clear(hashtable_name,h) #メモリはそのまま
ハッシュテーブルのリサイズ
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
..
kh_resize(hashtable_name,h,s) #sはリサイズ数
ハッシュテーブルにkeyを挿入(valueはまだ)
int ret;
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
...
kh_put(hashtable_name,h,key,&ret)
ret変数の解釈
keyがハッシュテーブルに存在する場合は0,存在しない場合は1
戻り値:
挿入された要素のイテレータ、この時点ではhashtableにvalueのための領域(bucketと呼んでいる模様)がputされた
だけでvalue自体はまだ。
ハッシュテーブルからキーを削除する
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
...
kh_put(hashtable_name,h,key,&ret)
...
kh_del(hashtable_name,h,key)
ハッシュテーブルのkeyにデータが入っているかテストする
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
...
kh_put(hashtable_name,h,key,&ret)
...
kh_exist(h,key)
戻り値:データがあれば1,なければ0
ハッシュテーブルの要素数を取得
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
...
kh_size(h)
ハッシュテーブル内のバケット数を取得する
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
...
khint_t size = kh_n_buckets(h)
イーサレータ
ハッシュテーブルからkeyに対応したイーサレータを取得
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
...
khiter_t iter;
iter = kh_get(hashtable_name,h,key)
イータレータを指定してkeyを取得
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
...
kh_put(hashtable_name,h,key,&ret)
...
kh_key(h,iter)
イータレータを指定してvalueを取得、設定
khash_t(hashtable_name) *h = kh_init(hashtable_name) #hashtable_nameはハッシュテーブルの名前
...
kh_put(hashtable_name,h,key,&ret)
...
kh_val(h,iter) #kh_value(h,iter)としてもOK
スタートイータレータを取得
kh_begin(h) #最初のイータレータを返す
エンドイータレータを取得
kh_end(h) #最後のイータレータを返す
ハッシュテーブルの破壊
kh_destroy
khash_t(hashtable_name) *h = kh_init(hashtable_name)
....
kh_destroy(hashtable_name,h)