
4.5 ハッシュ法 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 番号 | 以下をクリックすると,該当箇所にジャンプします |
| (1) | ハッシュ法(hashing)とは |
| (2) | キー値の衝突 |
| (3) | チェイン法 |
| (4) | オープンアドレス法 |
| (5) | 文字列のハッシュ値 |


| 番号 | 以下をクリックすると,該当箇所にジャンプします |
| (1) | ハッシュ法(hashing)とは |
| (2) | キー値の衝突 |
| (3) | チェイン法 |
| (4) | オープンアドレス法 |
| (5) | 文字列のハッシュ値 |


| ■チェイン法 | :同一値をもつ要素を線形リストで管理する方法 |
| ■オープンアドレス法 | :空きバケットを見つけるまでハッシュを繰り返す方法 |
| 番号 | 以下をクリックすると,該当箇所にジャンプします |
| (1) | ハッシュ法(hashing)とは |
| (2) | キー値の衝突 |
| (3) | チェイン法 |
| (4) | オープンアドレス法 |
| (5) | 文字列のハッシュ値 |
| // データ宣言 public struct NumberListData { public int Data; public int Pointer; } public const int AREASIZE = 50; public const int HASHSIZE = 16; public int ErasePointer; public static NumberListData[] NumberList=new NumberListData[AREASIZE]; public int[] Bucket=new int[HASHSIZE]; // バケット領域の初期化 public void BucketInitialize() { for(int i=0;i<Bucket.Length;i++) Bucket[i]=-1; } // 線形リスト格納領域の管理 public void AreaInitialize() { int i; for(i=0;i<NumberList.Length;i++) NumberList[i].Pointer=i+1; NumberList[NumberList.Length-1].Pointer=-1; ErasePointer=0; } public int GetArea() { if (ErasePointer<0) return -1; int P=ErasePointer; ErasePointer=NumberList[ErasePointer].Pointer; return P; } public void FreeArea(int P) { NumberList[P].Pointer=ErasePointer; ErasePointer=P; } // 線形リストの操作 public int replaca(int P, int A) { NumberList[P].Data=A; return P; } public int replacd(int P, int A) { NumberList[P].Pointer=A; return A;} public int car(int P) { return NumberList[P].Data;} public int cdr(int P) { return NumberList[P].Pointer;} public int cons(int A, int B) { int P=GetArea(); if(P<0) return -1; NumberList[P].Data=A; NumberList[P].Pointer=B; return P; } // 処理初期設定と共通ルーチン private void Form1_Load(object sender, System.EventArgs e) { BucketInitialize(); AreaInitialize(); ポインタ部の表示(); } private void ポインタ部の表示() { listBox1.Items.Clear(); listBox1.Items.Add("Erase Pointer=" + ErasePointer.ToString()); listBox1.Items.Add("(ポインタ部のみ)"); int i=ErasePointer; while(i>=0) { i=cdr(i);listBox1.Items.Add(i.ToString());} } // 領域管理のテスト private void button1_Click(object sender, System.EventArgs e) { int P=GetArea(); string PS=P.ToString(); textBox1.Text=PS; ポインタ部の表示(); MessageBox.Show (PS); } private void button2_Click(object sender, System.EventArgs e) { FreeArea(int.Parse(textBox1.Text)); ポインタ部の表示(); } // ハッシュテーブルの表示 private void ハッシュ表示() { string S; int P; listBox1.Items.Clear(); for(int i=0;i<Bucket.Length;i++) { S=i.ToString()+" "; P=Bucket[i]; if(P>=0) { while(P>=0) { S += " " + car(P).ToString(); P=cdr(P); } listBox1.Items.Add(S); } else listBox1.Items.Add(S+"(空)"); } } // 線形リストの表示 private int SearchKey(int Key, int P) { int PP=P; while(PP>=0) { if(car(PP)==Key) return PP; PP=cdr(PP); } return -1; } // ハッシュ設定 private void ハッシュ設定(int Key, int Mod) { int ID = Key % Mod; if(SearchKey(Key, Bucket[ID])<0) Bucket[ID]=cons(Key, Bucket[ID]); } private void button3_Click(object sender, System.EventArgs e) { int Mod = Bucket.Length; int Key = int.Parse(textBox1.Text) ; ハッシュ設定(Key, Mod); ハッシュ表示(); } // ハッシュ探索 private int ハッシュ探索(int Key, int Mod) { int ID = Key % Mod; return SearchKey(Key, Bucket[ID]); } private void button4_Click(object sender, System.EventArgs e) { int Mod = Bucket.Length; int Key = int.Parse(textBox1.Text) ; int P = ハッシュ探索(Key, Mod); MessageBox.Show(P.ToString()); } // ハッシュ削除 private int ハッシュ削除(int Key, int Mod) { int ID = Key % Mod; int Befor = -1; int P = Bucket[ID]; if(P<0) return -1; while(P >= 0) { if(car(P) == Key) break; Befor = P; P = cdr(P); } int After = cdr(P); FreeArea(P); if(Befor < 0) Bucket[ID] = After; else replacd(Befor, After); return After; } private void button5_Click(object sender, System.EventArgs e) { int Mod = Bucket.Length; int Key = int.Parse(textBox1.Text) ; int P = ハッシュ削除(Key, Mod); ハッシュ表示(); } |
| 番号 | 以下をクリックすると,該当箇所にジャンプします |
| (1) | ハッシュ法(hashing)とは |
| (2) | キー値の衝突 |
| (3) | チェイン法 |
| (4) | オープンアドレス法 |
| (5) | 文字列のハッシュ値 |


| 番号 | 以下をクリックすると,該当箇所にジャンプします |
| (1) | ハッシュ法(hashing)とは |
| (2) | キー値の衝突 |
| (3) | チェイン法 |
| (4) | オープンアドレス法 |
| (5) | 文字列のハッシュ値 |
| private int ハッシュ値(string S, int H) { int CH = 0; for(int i = 0; i < S.Length; i++) { CH +=(int) (S[i] % H); CH %= H; } return CH; } |
| ■削除マーク | : “\n” |
| ■未登録バケット | : “\r” |
| private const int HASHVALUE=16; private string[] Bucket = new string[HASHVALUE*2]; private void ハッシュ登録(string Str, int HashMod) { int ID=ハッシュ値(Str, HashMod); while(Bucket[ID]!="\r" && Bucket[ID]!="\n" && ID<Bucket.Length) { if(Str==Bucket[ID]) { MessageBox.Show("同一文字列が登録されています"); return; } ID++; } if (ID>=Bucket.Length)MessageBox.Show("登録できません"); else Bucket[ID]=Str; } private int ハッシュ探索(string Str, int HashMod) { int ID=ハッシュ値(Str, HashMod); while(Bucket[ID]!="\r" && ID<Bucket.Length) { if(Str==Bucket[ID]) return ID; ID++; } return -1; } private void ハッシュ削除(string Str, int HashMod) { int ID = ハッシュ探索(Str , HashMod); if(ID>=0) Bucket[ID]="\n"; } private void ハッシュ表示() { listBox1.Items.Clear(); for(int i=0;i<Bucket.Length;i++) { if(Bucket[i]=="\r") listBox1.Items.Add("----"); else if(Bucket[i]=="\n") listBox1.Items.Add("****"); else listBox1.Items.Add(Bucket[i]); } } private void button1_Click(object sender, System.EventArgs e) { string V = textBox1.Text; ハッシュ登録(V , HASHVALUE); ハッシュ表示(); } private int ハッシュ値(string S, int H) { int CH = 0; for(int i = 0; i < S.Length; i++) { CH +=(int) (S[i] % H); CH %= H; } return CH; } private void Form1_Load(object sender, System.EventArgs e) { for(int i=0;i<Bucket.Length;i++) Bucket[i]="\r"; ハッシュ表示(); } private void button2_Click(object sender, System.EventArgs e) { string V = textBox1.Text; int ID = ハッシュ探索(V , HASHVALUE); listBox1.SelectedIndex = ID; } private void button3_Click(object sender, System.EventArgs e) { string V = textBox1.Text; ハッシュ削除(V , HASHVALUE); ハッシュ表示(); } // listBox1が選択されたら,その文字列をtextBox1に移す。 private void listBox1_SelectedIndexChanged (object sender, System.EventArgs e) { textBox1.Text=listBox1.Text; } |
| 番号 | 以下をクリックすると,該当箇所にジャンプします |
| (1) | ハッシュ法(hashing)とは |
| (2) | キー値の衝突 |
| (3) | チェイン法 |
| (4) | オープンアドレス法 |
| (5) | 文字列のハッシュ値 |