Rubyã®ããã·ã¥ãã¼ãã«ã®ä»çµã¿ãå¾¹åºçã«ç解ãã
ããã·ã¥ã¨ã¯
ä¸è¬çã«ç解ããã¨æ½è±¡çã§åããé£ããªã£ã¦ãã¾ãããããã·ã¥ã¨ã¯ããããã¼ã¿ãããä¸å®ã®è¨ç®ããã¦æ±ãããç®çã«æ²¿ã£ãæ°å¤ãã¨æã£ã¦ãããããã§ã¯ãã©ã®ãããªç®çã«å©ç¨ãããã®ãï¼èªåã®ç¥èã§èãã¦ã¿ãã
- æå·å
- webã¢ããªã±ã¼ã·ã§ã³çã§ããã¹ã¯ã¼ããDBã«ä¿åããæãçã®ãã¹ã¯ã¼ããããã·ã¥ã«å¤æãã¦ä¿åããã
- Digest::SHA1.hexdigestçã§æ±ããããã·ã¥ãããå ã®ãã¼ã¿ã復å ããã®ãé常ã«å°é£ã¨ããç¹æ§ãå©ç¨ããã
- ä¿åãã¦ãããã¹ã¯ã¼ãããã·ã¥ãããã¨ãæ¼æ´©ããã¨ãã¦ããä¸æ£å©ç¨ãé²æ¢ã§ããã
- ãã¹ã¯ã¼ããç §åããã¨ãããããã·ã¥ã«å¤æãã¦ãä¿åãã¦ãããã¹ã¯ã¼ãããã·ã¥ã¨ä¸è´ãããã©ããã§å¤æããã
- åçã®ç¢ºèª
- é·ãæååãã¼ã¿ãæ¯è¼ããæãå ¨ã¦ã®æåãçããããã§ãã¯ããã®ã¯é常ã«æéããããã
- ããããé·ãæååãã¼ã¿ãããã·ã¥ã«å¤æãã¦ãããããã·ã¥å士ãæ°å¤ã¨ãã¦æ¯è¼ããã°å¹çãè¯ãã
- æ¹ç«ã®ãã§ãã¯ã¨ãããã§ãã¯ãã¸ããã¨ãã¦å©ç¨ãã¦ãã¼ã¿éä¿¡æã®æååãæ¤åºãªã©ã®å©ç¨ãèããããã
- ããã·ã¥ãã¼ãã«ã«ããé«éæ¤ç´¢
- ããã·ã¥ãã¼ãã«ã¨ã¯ããã¼ã«å¯¾å¿ããå¤ããç¬æã«åãåºããã¨ãã§ãããã¼ãã«ã
- ãã¼ã¨å¤ããã¢ã«ãããã¼ãã«ãæ¤ç´¢ããæãifæã使ã£ã¦å
é ããé ã«ç
§åãã¦ããã¨ã以ä¸ã®åé¡ãçºçããã
- ãã¼ã®ä½ç½®ãæåããæå¾ãã«ãã£ã¦æ¤ç´¢æéãå¤ãã£ã¦ããã
- ãã¼ãå¢ããç¨ã«ãå¹³åã®æ¤ç´¢æéãå¢å ããã
- ãã®åé¡ã解決ããã«ã¯ãifæã«ãããã¼ã®ç §åãæ¢ããå¿ è¦ãããã
- ãã¼ãã¤ã³ããã¯ã¹ï¼å é ããä½çªç®ã®ãã¼ã¿ãã表ç¾ããæ°å¤ï¼ã«å¤æããã°ã対å¿ããå¤ã®æ ¼ç´ä½ç½®ãç¹å®ã§ããã
- ãã¼ãä½ä¸ä»¶ãããã¨ãã¤ã³ããã¯ã¹ãè¦ãã°ã対å¿ãããã¼ã¿ãç¬æã«åãåºããã®ã ã
ä»åãç解ãããã¨æã£ã¦ããã®ã¯ããã®ããã·ã¥ãã¼ãã«ã®ä»çµã¿ãRubyã§ã¯{:apple => 120, :orange => 100}ã®ããã«è¡¨ç¾ããã°ãHashãªãã¸ã§ã¯ããçæãããç°¡åã«å©ç¨ã§ããã便å©ãªã®ã§ãã使ããããã®è£ã§ãã©ã®ãããªä»çµã¿ã§å®ç¾ããã¦ããããæ°ã«ãããã¨ãç¡ãã£ããå½åãifæã§å°éã«æ¤ç´¢ãã¦ãããã ãããªãä½ã«ããèãã¦ããªãã£ããã¨ãã§ããªãï¼ãã£ã¨ç´ æ´ãããå¹ççãªä»çµã¿ãªã®ã«ã
Rubyã§ã¯ãHashãªãã¸ã§ã¯ãã«éãããäºç´èªã®æ¤ç´¢ã§ãå®å
¨ããã·ã¥é¢æ°ãå©ç¨ãã¦å¹ççã«å¦çããã¦ããããããããã·ã¥ãã¼ãã«ãç解ããã°ãããå¹ççãªå¦çæ¹æ³ãçºæ³ã§ãããããããªããç©äºãå¹ççã«å¦çããéè¦ãªæè¡ãªã®ã ã
Rubyã®ã½ã¼ã¹ã³ã¼ãã¨è§£èª¬
ã½ã¼ã¹ã³ã¼ãã¨è§£èª¬ã¯ä»¥ä¸ã®ãªã³ã¯ããåå¾ããã解説ããã¦ããã®ã¯ãruby 1.7.3 2002-09-12çã ããããã·ã¥ãã¼ãã«ã®ä»çµã¿ã«å¤§ããªå¤åã¯ç¡ããããªã®ã§ã1.8.7ã§ã大å¤åèã«ãªãã
ããã·ã¥ãã¼ãã«
ååã®æ¥è¨ï¼どのようにして一番右の1のビット位置を求めているのか?ã§ç解ãããMç³»åãæ´»ç¨ããæ¹æ³ããããã·ã¥ãã¼ãã«ãå©ç¨ãã¦ããã¨è¨ããã
- 1ã2ã4ã8ã16ã...ã9223372036854775808ï¼2ã®63ä¹ï¼ã¨ãã64ãããã®2ã®nä¹æ°å¤ãã0ãã63ã®æ°å¤ï¼ããã·ã¥ï¼ã«å¤æãã¦ããã
- å¤æããæã«éè¤ã¯ç¡ãã64ãããã®2ã®nä¹æ°å¤ã¯ãå¿ ã0ãã63ã®ãã£ãä¸ã¤ã®å¤ã¨å¯¾å¿ãã¦ããã
- ãã®ããã«éè¤ã®ç¡ãããã·ã¥ãå¾ããããã¨ãå®å ¨ããã·ã¥ã¨è¨ãã
- ããããã®å ´åãå¤æãããæ°å¤ã0ãã63ã§ãå¤æåã®è¦ç´ æ°ã¨ã´ã£ããä¸è´ãã¦ãã¦ç¡é§ãç¡ãã
- ãã®ãããªå®å ¨ç¡é§ç¡ãããã·ã¥ããåç´ãªæ¼ç®ã ãã§å®ç¾ã§ãã¦ãã¾ãã·ã³ãã«ããåãã¨ããã
ä¸æ¹ãMç³»åãå©ç¨ããªãã§ãRubyã®ããã·ã¥ã§å®è£ ãã¦ãããã¯ãããã·ã¥ãã¼ãã«ãå©ç¨ããã訳ã ãç®ã«è¦ããRubyã³ã¼ãã¯ããã®ãããã·ã³ãã«ãããããå é¨çãªCè¨èªã®å¦çã¯é¥ãã«è¤éã ãããã·ã¥ã«å¤æããæ¹æ³ããããã·ã¥ãã¼ãã«ã®æ§é ããããã¯ããããããã¼ãããã·ã¥ã«å¤æãã¦ãããã·ã¥ã¯éè¤ããå¯è½æ§ããããããã§ãç確ã«æ¤ç´¢ã§ããããã«ãã¦ããããã ã
- Rubyã®ããã·ã¥ãã¼ãã«ã¯ãåç´ãªé åã§ã¯ãªããst_tableã¨ããæ§é ä½ã§ããã
- st_tableã¯ãããã«st_table_entryã¨ããæ§é ä½ã¸ã®ãã¤ã³ã¿ãè¤æ°æã£ã¦ããã
- st_table_entryã¯ã以ä¸ã®è¦ç´ ãæã£ã¦ããã
- ãã¼ãå¤æããããã·ã¥ã
- ãã¼ã
- å¤ã
- 次ã®st_table_entryã¸ã®ãã¤ã³ã¿
- ãã¼ãå¤æããããã·ã¥ã¯éè¤ããå¯è½æ§ãããã®ã§...
- ããã·ã¥ãã¼ãã«ã§ãããããst_table_entryã®ãã¼ãè¦ã¦ãéè¤ããå¥ã®ãã¼ã§ãªãã確èªããã
- ãããéè¤ãã¦ããå¥ã®ãã¼ã§ããã°ã次ã®st_table_entryã«ç§»åãã¦ãä¸è´ãããã¼ãè¦ã¤ããã¾ã§ç¹°ãè¿ãã
- ãã¼ãä¸è´ãã¦ããããå¤ãèªã¿åºãã¦è¿ãã
ã¤ã¾ãããã¼ãä¸è´ããã¾ã§ããã¤ã³ã¿ãæã示ãst_table_entryã¸ã®ç§»åãç¹°ãè¿ããã¨ã«ãªãããã¼å¤ã®æ¤ç´¢ã¯ã¾ãããã·ã¥ãã¼ãã«ã§è¡ããããã·ã¥ãéè¤ãã¦ããå ´åã¯ããã«ifæã§æ¯è¼ç §åãããã¨ãããã¤ããªãããªããã·ã¥ãã¼ãã«ã«ãªã£ã¦ããã
図5: st_tableのデータ構造
-
-
- ä¸è¨ã®ä»çµã¿ã¯ããã§ã¤ã³æ³ã¨ãããã¢ã«ã´ãªãºã ã¨ãã¦ç¢ºç«ãããææ³ã§ãã£ãã
- åèãã¼ã¸:アルゴリズムとデータ構造編 第14章 ハッシュ探索�(チェイン法)
- 大å¤åèã«ãªãã¾ãããæè¬ã§ãï¼その他のアルゴリズム解説ãç´ æ´ãããã§ãï¼
-
st_tableã«é¢é£ããæ§é ä½
- å³5ã®æ§é ä½ã¯ã以ä¸ã®ããã«å®ç¾©ããã¦ããã
/* ---------- ruby_1_8_7/st.h ---------- */ #if SIZEOF_LONG == SIZEOF_VOIDP typedef unsigned long st_data_t; #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP typedef unsigned LONG_LONG st_data_t; #else # error ---->> st.c requires sizeof(void*) == sizeof(long) to be compiled. <<---- #endif struct st_hash_type { int (*compare)(); int (*hash)(); }; struct st_table { struct st_hash_type *type; int num_bins; int num_entries; struct st_table_entry **bins; };
/* ---------- ruby_1_8_7/st.c ---------- */ struct st_table_entry { unsigned int hash; st_data_t key; st_data_t record; st_table_entry *next; };
ãã¤ã³ã¿ã®ãã¤ã³ã¿
- st_tableã®struct st_table_entry **binsã¯ããã¤ã³ã¿ãã¼ã¯ãäºã¤ä»ãã¦ããã
- ã¤ã¾ããポインタのポインタãã¨è¨ããã¨ã«ãªããä½ã ãé ãæ··ä¹±ããã...
- binsã¯é åãæãã¦ãã¦ããããã®é åã«å¤ãä¿åããã¦ããã°ãå¤ã®å *bins ã¨ãªãã¯ããªã®ã ãã
- ããã«ã¯ããã«ãst_table_entryã¸ã®ãã¤ã³ã¿ãããã¤ãåãããã¦ããã
- ã ããããst_table_entryã¸ã®ãã¤ã³ã¿åã®ããã¤ã³ã¿ã ãããã¨ç解ããã°ãå°ãã¯åããæãã ãããï¼
(st_table_entry*) (*bins)
- ã¡ãªã¿ã«ãbins㯠st_init_table_with_size() ã§åå¾ããã¦ãããï¼ä»¥ä¸ã®é¢æ°ãã¤ã³ã¿ã§æç²ããã³ã¼ãåç §ï¼
tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
é¢æ°ãã¤ã³ã¿
- ã¨ããã§ãst_tableã®ä¸ã«ãst_hash_typeã¨ããï¼èªåã«ã¨ã£ã¦ï¼è¦æ £ããªãæ§é ä½ããããã¨ã«æ°ä»ãã
- ããã¯ã関数を指し示すポインタã®æ§é ä½ã§ããã
- é¢æ°ãã¤ã³ã¿ã§ããcompareãhashã«ãç¹å®ã®é¢æ°ãæå®ããã°ããã®é¢æ°ããã¤ã³ã¿èå¥åã§å¼ã³åºããã¨ãã§ããã
ä¾ï¼
- st_init_numtableãå¼ã³åºãã¦çæãããst_tableã§ã¯...
-
-
- xcallocã¨ã¯ï¼
-
/* ---------- ruby_1_8_7/st.c ---------- */ #ifdef RUBY #define malloc xmalloc #define calloc xcalloc #endif #define alloc(type) (type*)malloc((unsigned)sizeof(type)) #define Calloc(n,s) (char*)calloc((n),(s)) st_table* st_init_numtable(void) { return st_init_table(&type_numhash); } st_init_table(type) struct st_hash_type *type; { return st_init_table_with_size(type, 0); } st_table* st_init_table_with_size(type, size) struct st_hash_type *type; int size; { st_table *tbl; ...ï¼ä¸ç¥ï¼... size = new_size(size); /* round up to prime number */ tbl = alloc(st_table); tbl->type = type; /* tbl->type->compare = numcmp; tbl->type->hash = numhash; */ tbl->num_entries = 0; tbl->num_bins = size; tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); return tbl; } static struct st_hash_type type_numhash = { numcmp, numhash, }; static int numcmp(x, y) long x, y; { return x != y; } static int numhash(n) long n; { return n; }
- st_tableã®ã¡ã³ãåãæå®ãã¦ãnumcmp(x,y)ãããã¯numhash(n)ãå¼ã³åºããã¨ãã§ããã
(*table->type->compare)(x,y); /* numcmp(x, y)ã¨åç */ (*table->type->hash)(n); /* numhash(n)ã¨åç */
- ãªããããããä¸è¨ã®ãããªé åããªé¢æ°å¼ã³åºããããã®ãï¼
- ããã¯ãst_hash_typeã®æå®ãå¤æ´ããã ãã§ãããã·ã¥ãã¼ãã«ã®ç¨®é¡ã«å¿ããæ¯è¼ï¼compareï¼ãããã·ã¥å¤æï¼hashï¼ãå¼ã³åºããã¨ãã§ããããã
- ããã·ã¥ãã¼ãã«ã¯ãRubyã®ãããããªé¨åã§æ´»èºãã¦ããã
- ããããå©ç¨ããå ´æã«ãã£ã¦ãããã·ã¥ãã¼ãã«ã®ç¨®é¡ãå°ãã ãç°ãªãã
- ä¸è¨ã®type_numhashã¯ãrubyã®ã¤ã³ã¿ããªã¿ã§ãã使ãããã¿ã¤ããããã
- Rubyã³ã¼ãã®ä¸ã§ä½¿ãHashãªãã¸ã§ã¯ãã§ã¯ãobjhashã¨ããã¿ã¤ãã使ããã¦ããã
ã¤ã¾ãããªãã¸ã§ã¯ãæåã§ãªãCè¨èªã§ããªãã¸ã§ã¯ãæåçã«ããã·ã¥ãã¼ãã«ãç¶æ¿ãããããªå¹æãçã£ã¦ããã®ã ãã³ã¼ãã®éè¤ãæå°éã«ããããã«ã
Hashãªãã¸ã§ã¯ãã®å®è£
- ããã§ã¯ãRubyã³ã¼ãã®ä¸ã§å©ç¨ãããã¿ã¤ãã®éãHashãªãã¸ã§ã¯ãã®å®è£
ã追ã£ã¦ã¿ãã
- ä¸çªä¸ã®rb_hash_new()ããRubyã³ã¼ãã®Hash.newã«å¯¾å¿ããã¨æãããã
# ---------- ruby_1_8_7/hash.c ---------- static int rb_any_cmp(a, b) VALUE a, b; { VALUE args[2]; if (a == b) return 0; if (FIXNUM_P(a) && FIXNUM_P(b)) { return a != b; } if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString && TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) { return rb_str_cmp(a, b); } if (a == Qundef || b == Qundef) return -1; if (SYMBOL_P(a) && SYMBOL_P(b)) { return a != b; } args[0] = a; args[1] = b; return !rb_with_disable_interrupt(eql, (VALUE)args); } static int rb_any_hash(a) VALUE a; { VALUE hval; int hnum; switch (TYPE(a)) { case T_FIXNUM: case T_SYMBOL: hnum = (int)a; break; case T_STRING: hnum = rb_str_hash(a); break; default: hval = rb_funcall(a, id_hash, 0); if (!FIXNUM_P(hval)) { hval = rb_funcall(hval, '%', 1, INT2FIX(536870923)); } hnum = (int)FIX2LONG(hval); } hnum <<= 1; return RSHIFT(hnum, 1); } static struct st_hash_type objhash = { rb_any_cmp, rb_any_hash, }; static VALUE hash_alloc0(klass) VALUE klass; { NEWOBJ(hash, struct RHash); OBJSETUP(hash, klass, T_HASH); hash->ifnone = Qnil; return (VALUE)hash; } static VALUE hash_alloc(klass) VALUE klass; { VALUE hash = hash_alloc0(klass); /* Hashãªãã¸ã§ã¯ããæã¤ããã·ã¥ãã¼ãã«ã«ãobjhashã¿ã¤ãã§åæåããããã·ã¥ãã¼ãã«ãè¨å®ãã */ RHASH(hash)->tbl = st_init_table(&objhash); return hash; } VALUE rb_hash_new() { return hash_alloc(rb_cHash);/* rb_cHash = rb_define_class("Hash", rb_cObject); */ }
/* ---------- ruby_1_8_7/string.c ---------- */ int rb_str_hash(str) VALUE str; { register long len = RSTRING(str)->len; register char *p = RSTRING(str)->ptr; register int key = 0; #if defined(HASH_ELFHASH) register unsigned int g; while (len--) { key = (key << 4) + *p++; if (g = key & 0xF0000000) key ^= g >> 24; key &= ~g; } #elif defined(HASH_PERL) while (len--) { key += *p++; key += (key << 10); key ^= (key >> 6); } key += (key << 3); key ^= (key >> 11); key += (key << 15); #else while (len--) { key = key*65599 + *p; p++; } key = key + (key>>5); #endif return key; }
/* ---------- ruby_1_8_7/ruby.h ---------- */ struct RHash { struct RBasic basic; struct st_table *tbl; int iter_lev; VALUE ifnone; };
- Hashãªãã¸ã§ã¯ãã®ãã¼ã«ã¯ãæ°å¤ã»ã·ã³ãã«ã»æååãå©ç¨ã§ããã
- st_tableã®typeãobjhashã«ãªãã¨ã以ä¸ã®compareã»hashãå¼ã³åºããããã¨ã«ãªãã
(*table->type->compare)(x,y); /* rb_any_cmp(x, y)ã¨åç */ (*table->type->hash)(n); /* rb_any_hash(n)ã¨åç */
- rb_any_cmpã»rb_any_hashã®ä¸ã§ããã¼ã®ç¨®é¡ã«å¿ãã¦å¦çããã¦ããã
ããã·ã¥ã®æ¤ç´¢æ¹æ³
- ã¾ãããã¯ãå®ç¾©ãããdo_hash(key,table)ãå®è¡ãããã¨ã§ãããã·ã¥å¤æãå§ã¾ãã......ï¼4ï¼
- (*(table)->type->hash)( (key) )ã¯ããã¤ã³ã¿ã«ããé¢æ°å¼ã³åºãã......ï¼1ï¼
- ããã·ã¥ãã¼ãã«ã®ã¿ã¤ãã«å¿ããããã·ã¥å¤æé¢æ°ãå¼ã³åºãããã
- FIND_ENTRY()ã¯ãã¼ã«å¯¾å¿ããã¨ã³ããªãæ¤ç´¢ãã......ï¼5ï¼
- æ±ããããã·ã¥hash_valãããã¼ãã«ãµã¤ãº(table)->num_binsã§å²ã£ãä½ãããæ±ããã¨ã³ããªã®ç¸å¯¾ä½ç½®bin_posã示ãã......ï¼2ï¼
- ããã·ã¥ãã¼ãã«ã®å é ããbin_posãã¤ã³ããã¯ã¹æå®ãã¦ãæ±ããã¨ã³ããªã®ãã¤ã³ã¿ptrãåå¾ããã......ï¼3ï¼
- åå¾ããã¨ã³ããªã®ãã¤ã³ã¿ptrããæããã¦ãæ¤ç´¢ãã¼ã¨ä¸è´ãã¦ããããã§ãã¯ããã......ï¼Cï¼
- PTR_NOT_EQUAL()ã¨EQUAL()ãã¯ãã«ãã£ã¦ããã¼ãä¸è´ãã¦ããªãã¨trueãè¿ãã......ï¼Bï¼
- (*table->type->compare)( (x),(y) )ã§ããã·ã¥ãã¼ãã«ã®ã¿ã¤ãã«å¿ããæ¯è¼ãããã......ï¼Aï¼
- COLLISION;ã¯ãããã°ç¨ã®ãã¯ããªã®ã§ãç¡è¦ãã¦OKãããã
- ãã¼ãä¸è´ãã¦ããªããã°ã次ã®ãã¤ã³ã¿ã«ç§»åããããã¼ãä¸è´ããã¾ã§ç¹°ãè¿ãã......ï¼Dï¼
- æå¾ã® ptr = ptr->next; ãä¸è¦ãªæ°ããããã......ï¼Eï¼
- if 㨠whileã®PTR_NOT_EQUALã®ç¬¬2å¼æ°ããptrã¨ptr->nextã§éã£ã¦ãããã¨ã«æ³¨æã
- if ã whileã«ç½®ãæããã°ãç¶ã4è¡ã¯ä¸è¦ã«ãªãããã ãã©ãCOLLISIONãæå¹ã«ãããããããã®ããã«ãã¦ããï¼
- æå¾ã«ãptr->recordã¨ããã°ããã¼ã«å¯¾å¿ããå¤ãåå¾ã§ããã
/* ---------- ruby_1_8_7/st.c ---------- */ #define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)((x),(y)) == 0) /* A */ #define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key)) /* 1 */ #define PTR_NOT_EQUAL(table, ptr, hash_val, key) \ /* B */ ((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key))) #define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ bin_pos = hash_val%(table)->num_bins;\ /* 2 */ ptr = (table)->bins[bin_pos];\ /* 3 */ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\ /* C */ COLLISION;\ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\ /* D */ ptr = ptr->next;\ }\ ptr = ptr->next;\ /* E */ }\ } while (0) int st_lookup(table, key, value) st_table *table; register st_data_t key; st_data_t *value; { unsigned int hash_val, bin_pos; register st_table_entry *ptr; hash_val = do_hash(key, table); /* 4 */ FIND_ENTRY(table, ptr, hash_val, bin_pos); /* 5 */ if (ptr == 0) { return 0; } else { if (value != 0) *value = ptr->record; return 1; } }
ããã·ã¥ãã¼ãã«ã®ãµã¤ãº
- ããã·ã¥ãã¼ãã«ã«å¿ è¦ãªãµã¤ãºã¯ãst_init_table_with_size()ã®ä¸ã§ãnew_size()ãå¼ã³åºãã¦è¨ç®ãã¦ããã
/* ---------- ruby_1_8_7/st.c ---------- */ /* * MINSIZE is the minimum size of a dictionary. */ #define MINSIZE 8 /* Table of prime numbers 2^n+a, 2<=n<=30. */ static long primes[] = { 8 + 3, 16 + 3, 32 + 5, 64 + 3, 128 + 3, 256 + 27, 512 + 9, 1024 + 9, 2048 + 5, 4096 + 3, 8192 + 27, 16384 + 43, 32768 + 3, 65536 + 45, 131072 + 29, 262144 + 3, 524288 + 21, 1048576 + 7, 2097152 + 17, 4194304 + 15, 8388608 + 9, 16777216 + 43, 33554432 + 35, 67108864 + 15, 134217728 + 29, 268435456 + 3, 536870912 + 11, 1073741824 + 85, 0 }; static int new_size(size) int size; { int i; #if 0 /* 決ãã¦å®è¡ãããªãããã㯠*/ for (i=3; i<31; i++) { if ((1<<i) > size) return 1<<i; } return -1; #else int newsize; for (i = 0, newsize = MINSIZE; i < sizeof(primes)/sizeof(primes[0]); i++, newsize <<= 1) { if (newsize > size) return primes[i]; } /* Ran out of polynomials */ return -1; /* should raise exception */ #endif }
ãã¼ãã«ãµã¤ãºã¯ãªãç´ æ°ãªã®ãï¼
- ãã¼ããå¤ãåå¾ããã«ã¯ãããã·ã¥%ãã¼ãã«ãµã¤ãºã§ä½ããåå¾ããããã®ä½ãããæ±ãããã¼ã®ã¤ã³ããã¯ã¹ã«ãªã£ã¦ããã
- ããã·ã¥ãã¼ãã«ãå¹çè¯ãå©ç¨ããã«ã¯ãã¤ã³ããã¯ã¹ã®éè¤ãç¡ããããã¼ã¨å¤ã1対1ã¨ãªãé¢ä¿ãç®æãå¿ è¦ãããã
- ãããå®ç¾ããããã«ãç´ æ°ã§å²ããã¨ã§ããã®ä½ããä¸æ§ã«ã°ãããå¤ã«ãªãããã ã
- 以ä¸ã®ãã¼ã¸ã§ãé¢ç½ãå®é¨çµæãè¦ããã¨ãã§ãããï¼å¤§å¤åèã«ãªãã¾ãããæè¬ã§ãï¼ï¼
- データ構造とアルゴリズム >> 表検索アルゴリズム >> ハッシュ検索 >> ハッシュ関数の選び方
ããã·ã¥ãã¼ãã«ã«ã¨ã³ããªã追å
- st_add_direct()ã¯ãã¨ã³ããªãç¡æ¡ä»¶ã«è¿½å ããã
- st_insert()ã¯ãããã·ã¥ãã¼ãã«ã«ãã¼ãåå¨ããã調ã¹ã¦...
- ãã¼ãåå¨ããªãæã ã追å ããã
- ãã¼ãåå¨ãããä¸æ¸ãããã
- ã©ã¡ããã追å ããæã¯ããã¯ãå®ç¾© ADD_DIRECT()ã§å¦çãã¦ããã
- ããã·ã¥ãã¼ãã«ãæ··éãã¦ãããã......if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY)
- ããã·ã¥ãã¼ãã«ã®ãµã¤ãºãåè¨å®ãã¦ãä½ãç´ãã......rehash(table)
- st_table_entryã«ãå¿ è¦äºé ãæ¸ãè¾¼ãã§ãst_tableã«è¿½å ãããst_tableã®ã¨ã³ããªæ°ã+1ããã
#define ST_DEFAULT_MAX_DENSITY 5 #define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ do {\ st_table_entry *entry;\ if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) {\ rehash(table);\ bin_pos = hash_val % table->num_bins;\ }\ \ entry = alloc(st_table_entry);\ /* æ°è¦ã¨ã³ããªãçæ */ \ entry->hash = hash_val;\ entry->key = key;\ entry->record = value;\ entry->next = table->bins[bin_pos];\ /* æ°è¦ã¨ã³ããªã®next â ä»ã¾ã§å é ã ã£ãã¨ã³ããªã®ä½ç½® */ table->bins[bin_pos] = entry;\ /* ããã·ã¥ãã¼ãã«ãæãå é ã®ã¨ã³ã㪠â æ°è¦ã¨ã³ããªã®ä½ç½® */ table->num_entries++;\ } while (0) int st_insert(table, key, value) register st_table *table; register st_data_t key; st_data_t value; { unsigned int hash_val, bin_pos; register st_table_entry *ptr; hash_val = do_hash(key, table); FIND_ENTRY(table, ptr, hash_val, bin_pos); if (ptr == 0) { ADD_DIRECT(table, key, value, hash_val, bin_pos); return 0; } else { ptr->record = value; return 1; } } void st_add_direct(table, key, value) st_table *table; st_data_t key; st_data_t value; { unsigned int hash_val, bin_pos; hash_val = do_hash(key, table); bin_pos = hash_val % table->num_bins; ADD_DIRECT(table, key, value, hash_val, bin_pos); } static void rehash(table) register st_table *table; { register st_table_entry *ptr, *next, **new_bins; int i, old_num_bins = table->num_bins, new_num_bins; unsigned int hash_val; new_num_bins = new_size(old_num_bins+1); new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*)); for(i = 0; i < old_num_bins; i++) { ptr = table->bins[i]; while (ptr != 0) { next = ptr->next; hash_val = ptr->hash % new_num_bins; ptr->next = new_bins[hash_val]; new_bins[hash_val] = ptr; ptr = next; } } free(table->bins); table->num_bins = new_num_bins; table->bins = new_bins; }
äºåç¥è
Cè¨èªã«çãã®ã§ã以ä¸ã®ãããªãã¨ããã¡ããã¨ç解ãã¦ããå¿ è¦ããã£ãã
#defineã®ãã¯ãæ©è½
- èªåã使ã£ããã¨ããã#defineã¯ã以ä¸ã®ãããªä½¿ãæ¹ã
#define PI 3.14 s = PI * r * r
- ããã¨ãCããªããã»ããµã¯ã以ä¸ã®ããã«ç½®ãæãã¦è§£éãã¦ãããã
s = 3.14 * r * r
- ã¤ã¾ãã#defineã¯ã第1å¼æ°ãã第2å¼æ°ã§ç½®ãæããã®ã ã
- ç½®ãæãã®æ©è½ããã¾ãå©ç¨ããã°ã以ä¸ã®ããã«é¢æ°å®ç¾©ã®ãããªä½¿ãæ¹ãå¯è½ã
#define PI 3.14 #define sq(r) ((r)*(r)) s = PI * sq(r)
- ããã¨ã以ä¸ã®ããã«è§£éãããã
s = 3.14 * ((r)*(r))
- ãªããã«ãã³ããã£ã±ãå¿ è¦ãªã®ãã¯ã以ä¸ã®ãã¼ã¸ã大å¤åèã«ãªãã¾ãããï¼æè¬ã§ãï¼ï¼
- ããã«ã以ä¸ã®ããã«ããã¨ãè¤æ°è¡ã«æ¸¡ãé¢æ°å®ç¾©ã®ããã«å©ç¨ã§ãã¦ãã¾ããªãã¦ï¼
#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ bin_pos = hash_val%(table)->num_bins;\ ptr = (table)->bins[bin_pos];\ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\ COLLISION;\ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\ ptr = ptr->next;\ }\ ptr = ptr->next;\ }\ } while (0) FIND_ENTRY(table, ptr, hash_val, bin_pos);
- ããã¨ã以ä¸ã®ããã«è§£éãããã®ã...ã
do { bin_pos = hash_val%(table)->num_bins; ptr = (table)->bins[bin_pos]; if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) { COLLISION; while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) { ptr = ptr->next; } ptr = ptr->next; } } while (0);
- è¤æ°ã®æã»å¼ããæããã¯ãå®ç¾©ã§ã¯ãå
¨ä½ãdo{ã}while(0)ã§å²ãã
- ãã®æ¹æ³ã¯ããã¯ããå®å ¨ã«å±éããããã®å¸¸å¥æ段ãããã
- Cè¨èªã®ããªããã»ã¹ã®ã¡ã¢(Hishidama's C pre-process Memo)ï¼å¤§å¤åèã«ãªãã¾ãããæè¬ã§ãï¼ï¼
- ã¾ããwhile(0)ã®å¾ã«ã;ããä»ããªãã®ããã¤ã³ããããã
- ãã¯ããå©ç¨ããæ㯠FIND_ENTRY(); ã¨ããã®ã§ãwhile(0); ã ã¨ã;ããäºéã«ãªã£ã¦ãã¾ã...ã
æ§é ä½ã¡ã³ãã¸ã®ã¢ã¯ã»ã¹
- pãpointåã®å¤æ°ã§ãããªãããã®ã¡ã³ãã«ã¯ã.ãã§åºåã£ã¦ã¢ã¯ã»ã¹ã§ããã
struct point{ float x; float y; }; struct point p; p.x = 100.0; p.y = 200.0;
- ãããpããã¤ã³ã¿ã§ãããªããã->ãã§åºåã£ã¦ã¢ã¯ã»ã¹ããå¿ è¦ãããã
struct point *p; p->x = 100.0; /* (*p).xã¨åç */ p->y = 200.0; /* (*p).yã¨åç */
- åèãã¼ã¸ï¼æ¬æä¸ä»¥å¤ã«ãã以ä¸ã®ãã¼ã¸ãåèã«ãªãã¾ãããæè¬ã§ãï¼ï¼
追è¨
- Rubyã®ããã·ã¥ãã¼ãã«ã®ãµã¤ãºï¼è¦ç´ ã®æ°ï¼ãç´ æ°ã§ãããã¨ã¯äºå®ãªã®ã ããä¸æ¦ã«ãç´ æ°ã§å²ã£ãä½ããä¸æ§ã«ã°ãããå¤ã«ãªããã¨ãããã¨ã§ã¯ãªãæ§ã ã
- ããã·ã¥ãªãã¸ã§ã¯ãã®æååãã¼ããå¤ã¸ã®ã¤ã³ããã¯ã¹ãæ±ããå¦ç
/* ---------- ruby_1_8_7/string.c ---------- */ int rb_str_hash(str) VALUE str; { register long len = RSTRING(str)->len; register char *p = RSTRING(str)->ptr; register int key = 0; ...ï¼ä¸ç¥ï¼... #else while (len--) { key = key*65599 + *p; p++; } key = key + (key>>5); #endif return key; }
- ãã®å¾ãä¸è¨é¢æ°ã§è¿ãããå¤ããç´ æ°ã§ããããã·ã¥ãã¼ãã«ãµã¤ãºã§å²ã£ãä½ãããå¤ã¸ã®ã¤ã³ããã¯ã¹
/* ---------- ruby_1_8_7/st.c ---------- */ #define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ bin_pos = hash_val%(table)->num_bins; ptr = (table)->bins[bin_pos];\ ...ï¼ä¸ç¥ï¼...
- ä¸æ¹ãst_hash_typeã®å ´åã®ãå¤ã¸ã®ã¤ã³ããã¯ã¹ãæ±ããå¦ç
static int numhash(n) long n; { return n; }
- ãã®å¾ã®å¦çã¯åæ§ã§ãFIND_ENTRY(table, ptr, hash_val, bin_pos)ãå®è¡ãããã
- ããã·ã¥ã®ã¿ã¤ãã«ãã£ã¦ã¯ãå ã®ãã¼ããã®ã¾ã¾ããã·ã¥ãã¼ãã«ãµã¤ãºã§å²ã£ã¦ãä½ããå©ç¨ãããã¨ãããã®ã ã
ç´ æ°ã§å²ãã®ã¯ãæ±ç¨çã«å©ç¨ããçºããªã®ããªï¼