[C++]Hashクラス・改訂版,
Posted by yama3 2008年 12月 19日. プログラミング 
かなり前に書いたハッシュのクラスファイル(http://yamablo.com/2008/11/14-005442.php)の訂正版になります。訂正版を公開するのを忘れてました。
想定は、2項目からなるデータをハッシュとして保持する状況を考えてます。2項目のうち1つはキーとなる項目で、残りの1項目は非キー項目です。
Hash.cpp
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define DATA_SIZE 256
- #define TABLE_SIZE 200
- // ハッシュ表に格納するデータの構造
- typedef struct data {
- char key[DATA_SIZE]; // 格納するキーのデータ
- char value[DATA_SIZE]; // 格納する非キーのデータ
- int flg; // 格納状態のフラグ
- } data;
- class Hash {
- public:
- data HashTable[TABLE_SIZE]; // ハッシュ表
- int collision; // データ格納時にコリジョンが発生した回数
- int stored; // データの格納数
- double StoredPerAll; // データの格納率
- private:
- // ハッシュ値を求める
- int HashValue( char *str ) {
- int idx; // インデックスカウンタ
- int length; // 文字列の長さを格納
- int h = 0; // ハッシュ値を格納
- length = strlen( str );
- for( idx=0; idx<length; idx++ ) {
- h = h * 37 + str[idx];
- }
- h = h % TABLE_SIZE;
- return abs(h);
- }
- public:
- /* ******************************************
- * データstrの格納場所を求める
- * もし存在しなければ、-1を返す
- * ****************************************** */
- int where( char *str ) {
- int h;
- h = this->HashValue( str );
- // 該当場所のデータが空で、削除もしていないとき
- if( this->HashTable[h].flg == 0 ) {
- return -1;
- }
- // ハッシュ表の該当場所をチェックし、
- // その場所から目的のデータを探す
- while( strcmp(this->HashTable[h].key, str)!=0 ) {
- h++;
- if( h == TABLE_SIZE ) {
- h = 0;
- } else if( h == this->HashValue( str ) ) {
- // ハッシュ表を全て見てもなかった場合、Not Found
- return -1;
- }
- }
- return h;
- }
- // コンストラクタ
- Hash() {
- int idx;
- for( idx=0; idx<TABLE_SIZE; idx++ ) {
- this->HashTable[idx].key[0] = ’\0′;
- this->HashTable[idx].value[0] = ’\0′;
- this->HashTable[idx].flg = 0;
- }
- this->collision = 0;
- this->stored = 0;
- }
- // デストラクタ
- ~Hash() {
- // Do Nothing
- }
- /* ******************************************
- * ハッシュ表にデータを追加する
- * ****************************************** */
- void Add( data str ) {
- int h; // ハッシュ値を格納
- if( this->where( str.key ) == -1 ) {
- // ハッシュ値を計算しhに保存
- h = this->HashValue( str.key );
- // ハッシュ表の該当場所をチェックし、
- // 衝突していれば衝突回避するようにhを設定
- while( this->HashTable[h].flg == 1 ) {
- this->collision++;
- h++;
- if( h == TABLE_SIZE ) {
- h = 0;
- }
- }
- // データをハッシュ表に追加
- strcpy( this->HashTable[h].key, str.key );
- strcpy( this->HashTable[h].value, str.value );
- this->HashTable[h].flg = 1;
- this->stored = this->stored + 1;
- this->StoredPerAll = this->stored * 100 / TABLE_SIZE;
- }
- }
- /* ******************************************
- * データstrがこのハッシュで表現された集合に含まれるか
- * @return 0なら含まれない、1なら含まれる
- * ****************************************** */
- int member( char *str ) {
- if( this->where( str ) == -1 ) {
- return 0;
- } else {
- return 1;
- }
- }
- /* ******************************************
- * データstrをこのハッシュで表現された集合から削除
- * もし最初から存在しなければ、何もしないで終了
- * ****************************************** */
- void deletes( char *str ) {
- if( this->member( str ) == 1 ) {
- // データを削除する
- this->HashTable[this->where(str)].key[0] = ’\0′;
- this->HashTable[this->where(str)].value[0] = ’\0′;
- this->HashTable[this->where(str)].flg = -1;
- this->stored = this->stored - 1;
- this->StoredPerAll = this->stored * 100 / TABLE_SIZE;
- }
- }
- /* ******************************************
- * ハッシュからデータを取り出す
- * ****************************************** */
- data Get( char *keys ) {
- int idx; // キーkeysの格納場所
- data ret; // 戻り値として返すデータ
- idx = this->where( keys );
- strcpy( ret.key, HashTable[idx].key );
- strcpy( ret.value, HashTable[idx].value );
- return ret;
- }
- /* ******************************************
- * ハッシュの再構築
- * ****************************************** */
- void refresh() {
- int idx;
- int k = 0;
- data SwapTable[TABLE_SIZE];
- // データを退避用変数に格納する。
- for( idx=0; idx<TABLE_SIZE; idx++ ) {
- if( this->HashTable[idx].flg == 1 ) {
- strcpy( SwapTable[k].key, this->HashTable[idx].key );
- strcpy( SwapTable[k].value, this->HashTable[idx].value );
- SwapTable[k].flg = 1;
- k++;
- }
- }
- // テーブルをリセットする
- for( idx=0; idx<TABLE_SIZE; idx++ ) {
- this->HashTable[idx].flg = 0;
- this->HashTable[idx].key[0] = ’\0′;
- this->HashTable[idx].value[0] = ’\0′;
- }
- this->collision = 0;
- this->stored = 0;
- this->StoredPerAll = 0;
- // 退避したデータを格納する
- for( idx=0; idx<k; idx++ ) {
- this->Add( SwapTable[idx] );
- }
- }
- };
関連記事
[PR]
トラックバック
http://yamablo.com/2008/12/19-103002.php/trackback


11月 5th, 2009 at 12:38 AM
[...] http://yamablo.com/2008/12/19-103002.phpの記事にHashクラスの改訂版があります。 [...]