Open-Source-Software-Entwicklung und Downloads

Browse Subversion Repository

Diff of /trunk/TTProxy/YCL/include/YCL/Hashtable.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3226 by maya, Tue Mar 24 09:37:20 2009 UTC revision 3227 by maya, Tue Mar 24 15:10:33 2009 UTC
# Line 1  Line 1 
1  /*  /*
2   * $Id: Hashtable.h,v 1.4 2007-08-18 08:52:18 maya Exp $   * $Id: Hashtable.h,v 1.4 2007-08-18 08:52:18 maya Exp $
3   */   */
4    
5  #ifndef _YCL_HASHTABLE_H_  #ifndef _YCL_HASHTABLE_H_
6  #define _YCL_HASHTABLE_H_  #define _YCL_HASHTABLE_H_
7    
8  #if _MSC_VER >= 1000  #if _MSC_VER >= 1000
9  #pragma once  #pragma once
10  #endif // _MSC_VER >= 1000  #endif // _MSC_VER >= 1000
11    
12  #include <YCL/common.h>  #include <YCL/common.h>
13    
14  #include <YCL/HASHCODE.h>  #include <YCL/HASHCODE.h>
15  #include <YCL/ValueCtrl.h>  #include <YCL/ValueCtrl.h>
16  #include <YCL/Enumeration.h>  #include <YCL/Enumeration.h>
17  #include <YCL/Pointer.h>  #include <YCL/Pointer.h>
18    
19  namespace yebisuya {  namespace yebisuya {
20    
21  // ハッシュテーブルを管理するクラス。  // ハッシュテーブルを管理するクラス。
22  template<class TYPE_KEY, class TYPE_VALUE, class KEYCTRL = ValueCtrl<TYPE_KEY>, class VALCTRL = ValueCtrl<TYPE_VALUE> >  template<class TYPE_KEY, class TYPE_VALUE, class KEYCTRL = ValueCtrl<TYPE_KEY>, class VALCTRL = ValueCtrl<TYPE_VALUE> >
23  class Hashtable {  class Hashtable {
24          // TYPE_KEY, TYPE_VALUEにとれる型:          // TYPE_KEY, TYPE_VALUEにとれる型:
25          // ・デフォルトコンストラクタを持つ          // ・デフォルトコンストラクタを持つ
26          // ・コピーコンストラクタを持つ          // ・コピーコンストラクタを持つ
27          // ・==演算子を持つ          // ・==演算子を持つ
28          // ・=演算子を持つ(この条件のため参照は指定できない)          // ・=演算子を持つ(この条件のため参照は指定できない)
29          // KEYCTRL、VALCTRLにデフォルトのものを使用する場合は          // KEYCTRL、VALCTRLにデフォルトのものを使用する場合は
30          // ・デフォルトコンストラクタで生成されたインスタンスとNULLを比較すると真になる          // ・デフォルトコンストラクタで生成されたインスタンスとNULLを比較すると真になる
31          // ・NULLインスタンスとNULLを比較すると真になる          // ・NULLインスタンスとNULLを比較すると真になる
32          // ・TYPE_KEYはハッシュ値を生成するhashCodeメソッドを持つ          // ・TYPE_KEYはハッシュ値を生成するhashCodeメソッドを持つ
33          // が条件に加わる。          // が条件に加わる。
34  public:  public:
35          typedef Enumeration<TYPE_KEY> KeyEnumeration;          typedef Enumeration<TYPE_KEY> KeyEnumeration;
36          typedef Enumeration<TYPE_VALUE> ElementEnumeration;          typedef Enumeration<TYPE_VALUE> ElementEnumeration;
37  private:  private:
38          // コピーコンストラクタは使用禁止          // コピーコンストラクタは使用禁止
39          Hashtable(Hashtable&);          Hashtable(Hashtable&);
40          // 代入演算子は使用禁止          // 代入演算子は使用禁止
41          void operator=(Hashtable&);          void operator=(Hashtable&);
42    
43          // ハッシュテーブルのエントリ。          // ハッシュテーブルのエントリ。
44          struct Entry {          struct Entry {
45                  TYPE_KEY key;                  TYPE_KEY key;
46                  TYPE_VALUE value;                  TYPE_VALUE value;
47                  Entry() {                  Entry() {
48                          KEYCTRL::initialize(key);                          KEYCTRL::initialize(key);
49                          VALCTRL::initialize(value);                          VALCTRL::initialize(value);
50                  }                  }
51          };          };
52          // ハッシュテーブルのエントリを列挙するためのクラス。          // ハッシュテーブルのエントリを列挙するためのクラス。
53          class EnumEntries {          class EnumEntries {
54          private:          private:
55                  const Hashtable& table;                  const Hashtable& table;
56                  mutable int index;                  mutable int index;
57                  void skip()const {                  void skip()const {
58                          while (index < table.backetSize && VALCTRL::isEmpty(table.backet[index].value))                          while (index < table.backetSize && VALCTRL::isEmpty(table.backet[index].value))
59                                  index++;                                  index++;
60                  }                  }
61          public:          public:
62                  EnumEntries(const Hashtable& table)                  EnumEntries(const Hashtable& table)
63                  :table(table), index(0) {                  :table(table), index(0) {
64                          skip();                          skip();
65                  }                  }
66                  bool hasMoreEntries()const {                  bool hasMoreEntries()const {
67                          return index < table.backetSize;                          return index < table.backetSize;
68                  }                  }
69                  const Entry& nextEntry()const {                  const Entry& nextEntry()const {
70                          const Entry& entry = table.backet[index++];                          const Entry& entry = table.backet[index++];
71                          skip();                          skip();
72                          return entry;                          return entry;
73                  }                  }
74          };          };
75          friend class EnumEntries;          friend class EnumEntries;
76          // ハッシュテーブルのキーを列挙するためのクラス。          // ハッシュテーブルのキーを列挙するためのクラス。
77          class EnumKeys : public KeyEnumeration {          class EnumKeys : public KeyEnumeration {
78          private:          private:
79                  EnumEntries entries;                  EnumEntries entries;
80          public:          public:
81                  EnumKeys(const Hashtable& table)                  EnumKeys(const Hashtable& table)
82                  :entries(table) {                  :entries(table) {
83                  }                  }
84                  virtual bool hasMoreElements()const {                  virtual bool hasMoreElements()const {
85                          return entries.hasMoreEntries();                          return entries.hasMoreEntries();
86                  }                  }
87                  virtual TYPE_KEY nextElement()const {                  virtual TYPE_KEY nextElement()const {
88                          return entries.nextEntry().key;                          return entries.nextEntry().key;
89                  }                  }
90          };          };
91          // ハッシュテーブルの値を列挙するためのクラス。          // ハッシュテーブルの値を列挙するためのクラス。
92          class EnumValues : public ElementEnumeration {          class EnumValues : public ElementEnumeration {
93          private:          private:
94                  EnumEntries entries;                  EnumEntries entries;
95          public:          public:
96                  EnumValues(const Hashtable& table)                  EnumValues(const Hashtable& table)
97                  :entries(table) {                  :entries(table) {
98                  }                  }
99                  virtual bool hasMoreElements()const {                  virtual bool hasMoreElements()const {
100                          return entries.hasMoreEntries();                          return entries.hasMoreEntries();
101                  }                  }
102                  virtual TYPE_VALUE nextElement()const {                  virtual TYPE_VALUE nextElement()const {
103                          return entries.nextEntry().value;                          return entries.nextEntry().value;
104                  }                  }
105          };          };
106    
107          // エントリの配列。          // エントリの配列。
108          Entry* backet;          Entry* backet;
109          // エントリの配列のサイズ          // エントリの配列のサイズ
110          int backetSize;          int backetSize;
111          // 有効なエントリの数          // 有効なエントリの数
112          int count;          int count;
113          enum {          enum {
114                  // エントリの配列を大きくするときに使用するサイズ                  // エントリの配列を大きくするときに使用するサイズ
115                  BOUNDARY = 8,                  BOUNDARY = 8,
116          };          };
117          // keyと等しいキーを持つエントリのインデックスを返す。          // keyと等しいキーを持つエントリのインデックスを返す。
118          // 引数:          // 引数:
119          //      key     検索するキー          //      key     検索するキー
120          // 返値:          // 返値:
121          //      keyと等しいキーを持つか、まだ設定されていないエントリのインデックス。          //      keyと等しいキーを持つか、まだ設定されていないエントリのインデックス。
122          //      全てのエントリが設定済みでkeyと等しいものがなければ-1を返す。          //      全てのエントリが設定済みでkeyと等しいものがなければ-1を返す。
123          int find(const TYPE_KEY& key)const {          int find(const TYPE_KEY& key)const {
124                  int found = -1;                  int found = -1;
125                  int h = HASHCODE(key);                  int h = HASHCODE(key);
126                  for (int i = 0; i < backetSize; i++) {                  for (int i = 0; i < backetSize; i++) {
127                          int index = ((unsigned) h + i) % backetSize;                          int index = ((unsigned) h + i) % backetSize;
128                          const TYPE_KEY& bkey = backet[index].key;                          const TYPE_KEY& bkey = backet[index].key;
129                          if (KEYCTRL::isEmpty(bkey) || bkey == key) {                          if (KEYCTRL::isEmpty(bkey) || bkey == key) {
130                                  found = index;                                  found = index;
131                                  break;                                  break;
132                          }                          }
133                  }                  }
134                  return found;                  return found;
135          }          }
136          // エントリの配列を指定のサイズに変え、もう一度テーブルを作り直す。          // エントリの配列を指定のサイズに変え、もう一度テーブルを作り直す。
137          // 引数:          // 引数:
138          //      newSize 新しい配列のサイズ。          //      newSize 新しい配列のサイズ。
139          //                      有効なエントリの数よりも少なくしてはいけない。          //                      有効なエントリの数よりも少なくしてはいけない。
140          void rehash(int newSize) {          void rehash(int newSize) {
141                  Entry* oldBacket = backet;                  Entry* oldBacket = backet;
142                  int oldSize = backetSize;                  int oldSize = backetSize;
143                  backet = new Entry[newSize];                  backet = new Entry[newSize];
144                  backetSize = newSize;                  backetSize = newSize;
145                  for (int i = 0; i < oldSize; i++) {                  for (int i = 0; i < oldSize; i++) {
146                          if (!VALCTRL::isEmpty(oldBacket[i].value)) {                          if (!VALCTRL::isEmpty(oldBacket[i].value)) {
147                                  backet[find(oldBacket[i].key)] = oldBacket[i];                                  backet[find(oldBacket[i].key)] = oldBacket[i];
148                          }                          }
149                  }                  }
150                  delete[] oldBacket;                  delete[] oldBacket;
151          }          }
152  public:  public:
153          // デフォルトコンストラクタ。          // デフォルトコンストラクタ。
154          // 空のハッシュテーブルを作る。          // 空のハッシュテーブルを作る。
155          Hashtable()          Hashtable()
156          :backet(NULL), backetSize(0), count(0) {          :backet(NULL), backetSize(0), count(0) {
157          }          }
158          // エントリの配列の初期サイズを指定するコンストラクタ。          // エントリの配列の初期サイズを指定するコンストラクタ。
159          // 引数:          // 引数:
160          //      backetSize      エントリの配列の大きさ。          //      backetSize      エントリの配列の大きさ。
161          Hashtable(int backetSize)          Hashtable(int backetSize)
162          :backet(new Entry[backetSize]), backetSize(backetSize), count(0) {          :backet(new Entry[backetSize]), backetSize(backetSize), count(0) {
163          }          }
164          // デストラクタ。          // デストラクタ。
165          // エントリの配列を削除する。          // エントリの配列を削除する。
166          ~Hashtable() {          ~Hashtable() {
167                  delete[] backet;                  delete[] backet;
168          }          }
169          // 指定のキーに対応する値を取得する。          // 指定のキーに対応する値を取得する。
170          // 引数:          // 引数:
171          //      key     検索するキー          //      key     検索するキー
172          // 返値:          // 返値:
173          //      キーに対応する値。見つからなければNULLと等しい値を返す。          //      キーに対応する値。見つからなければNULLと等しい値を返す。
174          TYPE_VALUE get(const TYPE_KEY& key)const {          TYPE_VALUE get(const TYPE_KEY& key)const {
175                  TYPE_VALUE value;                  TYPE_VALUE value;
176                  VALCTRL::initialize(value);                  VALCTRL::initialize(value);
177                  int index = find(key);                  int index = find(key);
178                  if (index != -1)                  if (index != -1)
179                          value = backet[index].value;                          value = backet[index].value;
180                  return value;                  return value;
181          }          }
182          // 指定のキーに対応する値を設定する。          // 指定のキーに対応する値を設定する。
183          // 引数:          // 引数:
184          //      key     設定するキー          //      key     設定するキー
185          //      value 設定する値          //      value 設定する値
186          // 返値:          // 返値:
187          //      前にキーに設定されていた値。未設定だった場合はNULLと等しい値を返す。          //      前にキーに設定されていた値。未設定だった場合はNULLと等しい値を返す。
188          TYPE_VALUE put(const TYPE_KEY& key, const TYPE_VALUE& value) {          TYPE_VALUE put(const TYPE_KEY& key, const TYPE_VALUE& value) {
189                  int index = find(key);                  int index = find(key);
190                  if (index == -1) {                  if (index == -1) {
191                          rehash(backetSize + BOUNDARY);                          rehash(backetSize + BOUNDARY);
192                          index = find(key);                          index = find(key);
193                  }                  }
194                  TYPE_VALUE old = backet[index].value;                  TYPE_VALUE old = backet[index].value;
195                  if (VALCTRL::isEmpty(old)) {                  if (VALCTRL::isEmpty(old)) {
196                          count++;                          count++;
197                          backet[index].key = key;                          backet[index].key = key;
198                  }                  }
199                  backet[index].value = value;                  backet[index].value = value;
200                  return old;                  return old;
201          }          }
202          // 指定のキーに対応する値を削除する。          // 指定のキーに対応する値を削除する。
203          // 引数:          // 引数:
204          //      key     削除するキー          //      key     削除するキー
205          // 返値:          // 返値:
206          //      キーに設定されていた値。未設定だった場合はNULLと等しい値を返す。          //      キーに設定されていた値。未設定だった場合はNULLと等しい値を返す。
207          TYPE_VALUE remove(const TYPE_KEY& key) {          TYPE_VALUE remove(const TYPE_KEY& key) {
208                  TYPE_VALUE old;                  TYPE_VALUE old;
209                  VALCTRL::initialize(old);                  VALCTRL::initialize(old);
210                  int index = find(key);                  int index = find(key);
211                  if (index != -1) {                  if (index != -1) {
212                          old = backet[index].value;                          old = backet[index].value;
213                          if (!VALCTRL::isEmpty(old)) {                          if (!VALCTRL::isEmpty(old)) {
214                                  count--;                                  count--;
215                                  VALCTRL::initialize(backet[index].value);                                  VALCTRL::initialize(backet[index].value);
216                                  if (backetSize - count > BOUNDARY)                                  if (backetSize - count > BOUNDARY)
217                                          rehash(count);                                          rehash(count);
218                          }                          }
219                  }                  }
220                  return old;                  return old;
221          }          }
222          // キーを列挙するためのインスタンスを生成する。          // キーを列挙するためのインスタンスを生成する。
223          // 使用後はdeleteを忘れないように注意。          // 使用後はdeleteを忘れないように注意。
224          // 返値:          // 返値:
225          //      キーを列挙するためのインスタンス。          //      キーを列挙するためのインスタンス。
226          Pointer<KeyEnumeration> keys()const {          Pointer<KeyEnumeration> keys()const {
227                  return new EnumKeys(*this);                  return new EnumKeys(*this);
228          }          }
229          // 値を列挙するためのインスタンスを生成する。          // 値を列挙するためのインスタンスを生成する。
230          // 使用後はdeleteを忘れないように注意。          // 使用後はdeleteを忘れないように注意。
231          // 返値:          // 返値:
232          //      値を列挙するためのインスタンス。          //      値を列挙するためのインスタンス。
233          Pointer<ElementEnumeration> elements()const {          Pointer<ElementEnumeration> elements()const {
234                  return new EnumValues(*this);                  return new EnumValues(*this);
235          }          }
236          // 有効な値を持つキーの数を取得する。          // 有効な値を持つキーの数を取得する。
237          // 返値:          // 返値:
238          //      有効な値を持つキーの数。          //      有効な値を持つキーの数。
239          int size()const {          int size()const {
240                  return count;                  return count;
241          }          }
242          // 指定のキーが有効な値を持っているかどうかを判定する。          // 指定のキーが有効な値を持っているかどうかを判定する。
243          // 引数:          // 引数:
244          //      判定するキー。          //      判定するキー。
245          // 返値:          // 返値:
246          //      有効な値を持っていれば真。          //      有効な値を持っていれば真。
247          bool contains(const TYPE_KEY& key)const {          bool contains(const TYPE_KEY& key)const {
248                  int index = find(key);                  int index = find(key);
249                  return index != -1 && !VALCTRL::isEmpty(backet[index].value);                  return index != -1 && !VALCTRL::isEmpty(backet[index].value);
250          }          }
251          // 有効な値を一つも持っていないかどうかを判定する。          // 有効な値を一つも持っていないかどうかを判定する。
252          // 返値:          // 返値:
253          //      有効な値を一つも持っていなければ真。          //      有効な値を一つも持っていなければ真。
254          bool isEmpty()const {          bool isEmpty()const {
255                  return count == 0;                  return count == 0;
256          }          }
257          // 有効な値を一つも持っていない状態に戻す。          // 有効な値を一つも持っていない状態に戻す。
258          void empty() {          void empty() {
259                  delete[] backet;                  delete[] backet;
260                  backet = NULL;                  backet = NULL;
261                  backetSize = 0;                  backetSize = 0;
262                  count = 0;                  count = 0;
263          }          }
264  };  };
265    
266  }  }
267    
268  #endif//_YCL_HASHTABLE_H_  #endif//_YCL_HASHTABLE_H_

Legend:
Removed from v.3226  
changed lines
  Added in v.3227

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26