アルゴリズムとデータ構造1 2005年7月12日 酒居敬一([email protected]) http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/ALG2005/index.html public class MyHashtable { private MyHashtable() { } public MyHashtable(int aMaxSize) { this.table = new AddressData[aMaxSize]; } public AddressData get(String aKey) { if(null == aKey){ throw new NullPointerException(); } return this.table[this.calculateHashCode(aKey)]; } public void printAll() { for(int count = 0; count < this.table.length; count++){ System.out.println(count+1 + "\t" + this.table[count]); } System.out.println(); } private AddressData[] table; } public boolean put(AddressData anAddressData) { if(null == anAddressData){ return false; } this.table[this.calculateHashCode(anAddressData.getName())] = anAddressData; return true; [sakai@star]$ java MyHashtableTest } 住所データを格納 public boolean remove(String aKey) 1 null { 2 null if(null == aKey){ 3 null return false; 4 杉山: 稲城,東京 208 } 5 null this.table[this.calculateHashCode(aKey)] = null; 6 null return true; 7 ONGS Inc.: 渋谷,東京 151 } 8 後藤: 川崎,神奈川 214 private int calculateHashCode(String aKey) 9 null { 10 null if(null == aKey){ 11 佐々木: 座間,神奈川 228 throw new NullPointerException(); 12 小澤: 多摩,東京 206 } 13 null int intkey = 0; null for(int count = 0; count < aKey.length(); count++){ 14 15 null intkey += 0xFFFF & aKey.charAt(count); 16 null } 17 null return intkey % this.table.length; 18 null } 19 null 分離連鎖法(チェイン法) ハッシュ テーブル 連結リスト 図2.7.1 教科書125ページ public class AddressData { public AddressData(String aName, String aMetropolice, String aCity, String aZipcode) { if((null == aName) || (null == aMetropolice) || (null == aCity)|| (null == aZipcode)){ throw new NullPointerException(); } this.name = aName; this.metropolice = aMetropolice; 住所録として以下の項目を持つ this.city = aCity; •名前 this.zipcode = aZipcode; •市 } •都道府県 public String getName() { •郵便番号 return this.name; } public String getAddress() { return this.city + "," + this.metropolice + " " + this.zipcode; } public String toString() { return this.name + ": " + this.city + "," + this.metropolice + “ " + this.zipcode; } private String city; private String metropolice; private String name; private String zipcode; } public class ChainHashtable { private ChainHashtable() { } } public ChainHashtable(int aMaxSize) { this.table = new MyLinkedList[aMaxSize]; } private MyLinkedList[] table; public boolean put(AddressData anAddressData) { if(null == anAddressData){ return false; } int hashCode = this.calculateHashCode(anAddressData.getName()); if(null == this.table[hashCode]){ this.table[hashCode] = new MyLinkedList(); } this.table[hashCode].insert(anAddressData); return true; } public AddressData get(String aKey) { if(null == aKey){ throw new NullPointerException(); } MyLinkedList list = this.table[this.calculateHashCode(aKey)]; if(null == list){ return null; } int limit = list.size(); int count = 1; AddressData address = null; while(count <= limit){ address = (AddressData)list.get(count); if(address.getName().equals(aKey)){ return address; } private int calculateHashCode(String aKey) ++count; { } if(null == aKey){ return null; throw new NullPointerException(); } } int intkey = 0; for(int count = 0; count < aKey.length(); count++){ intkey += 0xFFFF & aKey.charAt(count); } return intkey % this.table.length; } public boolean remove(String aKey) { if(null == aKey){ return false; } MyLinkedList list = this.table[this.calculateHashCode(aKey)]; if(null == list){ return false; } int limit = list.size(); int count = 1; AddressData address = null; while(count <= limit){ address = (AddressData)list.get(count); if(address.getName().equals(aKey)){ return list.remove(count); } public void printAll() ++count; { } for(int count = 0; count < this.table.length; count++){ return false; if(null == this.table[count]){ } System.out.println(this.table[count]); }else{ this.table[count].printAll(); } } System.out.println(); } [sakai@star]$ java ChainHashtableTest 住所データを格納 杉山: 稲城,東京 208 佐々木: 座間,神奈川 228 → 小澤: 多摩,東京 206 ONGS Inc.: 渋谷,東京 151 → 後藤: 川崎,神奈川 214 データの取得: 後藤 後藤: 川崎,神奈川 214 杉山: 稲城,東京 208 佐々木: 座間,神奈川 228 → 小澤: 多摩,東京 206 ONGS Inc.: 渋谷,東京 151 → 後藤: 川崎,神奈川 214 データの削除: ONGS Inc. 杉山: 稲城,東京 208 佐々木: 座間,神奈川 228 → 小澤: 多摩,東京 206 後藤: 川崎,神奈川 214 [sakai@star]$ ハッシュ表の大きさが3なので 衝突が起きたときはリスト保持 開番地法 キー 既にデータが 格納されている ハッシュ 再ハッシュ ここも既にデータが 格納されている 再ハッシュの方法 •線形走査法 •二重ハッシュ法 •均一ハッシュ法 再ハッシュ この場所は空なので ここに格納する 図2.7.4 教科書131ページ および教科書134ページ 空き番地法を用いた場合の削除 キー 同じハッシュ値だけ ど、これじゃない。 ハッシュ 再ハッシュ 削除フラグを格納 削除したい 削除 データは消えてるけ ど、これでもない。 削除フラグ 再ハッシュ このデータを 探索したい これだっ! 教科書134ページ public class OpenAddressHashtable { public OpenAddressHashtable(int aMaxSize) { this.table = new AddressData[aMaxSize]; } private final AddressData removedData = new AddressData("", "", "", ""); private AddressData[] table; private int calculateHashCode(String aKey) } { 1回目のハッシュは剰余演算 2回目以降は一定間隔離す 距離は前の値から1~3 1の場合は線形走査法と同じ 2以上の場合は二重ハッシュ法 } if(null == aKey){throw new NullPointerException();} int intkey = 0; for(int count = 0; count < aKey.length(); count++){ intkey += 0xFFFF & aKey.charAt(count); } return intkey % this.table.length; private int calculateHashCodeAgain(String aKey, int aHashCode) { if(null == aKey){throw new NullPointerException();} int intkey = 0; for(int count = 0; count < aKey.length(); count++){ intkey += 0xFFFF & aKey.charAt(count); } int rehashCode = (aHashCode + 3 - (intkey % 3)) % this.table.length; System.err.println("再ハッシュ: " + aKey + " " + aHashCode + “ → " + rehashCode); return rehashCode; } public boolean put(AddressData anAddressData) { if(null == anAddressData){ return false; } int hashCode = this.calculateHashCode(anAddressData.getName()); if((null == this.table[hashCode]) || (this.removedData == this.table[hashCode])){ this.table[hashCode] = anAddressData; return true; } int limit = this.table.length -1; String key = anAddressData.getName(); for(int count = 0; count < limit; count++){ hashCode = this.calculateHashCodeAgain(key, hashCode); if((null == this.table[hashCode]) || (this.removedData == this.table[hashCode])){ this.table[hashCode] = anAddressData; return true; } } return false; } 1回目のハッシュで衝突が起きたときは 衝突が起きなくなるまで別のハッシュ関 数でハッシュしなおす。 public AddressData get(String aKey) { if(null == aKey){ throw new NullPointerException(); } int hashCode = this.calculateHashCode(aKey); if(null == this.table[hashCode]){ return null; } if(this.removedData != this.table[hashCode]){ if(this.table[hashCode].getName().equals(aKey)){ return this.table[hashCode]; } } int limit = this.table.length -1; for(int count = 0; count < limit; count++){ hashCode = this.calculateHashCodeAgain(aKey, hashCode); if(null == this.table[hashCode]){ return null; } if(this.removedData != this.table[hashCode]){ if(this.table[hashCode].getName().equals(aKey)){ return this.table[hashCode]; } } } return null; } public boolean remove(String aKey) { if(null == aKey){ throw new NullPointerException();} int hashCode = this.calculateHashCode(aKey); if(null == this.table[hashCode]){ return false; } if(this.removedData != this.table[hashCode]){ if(this.table[hashCode].getName().equals(aKey)){ this.table[hashCode] = removedData; return true; } } int limit = this.table.length -1; for(int count = 0; count < limit; count++){ hashCode = this.calculateHashCodeAgain(aKey, hashCode); if(null == this.table[hashCode]){ return false; } if(this.removedData != this.table[hashCode]){ if(this.table[hashCode].getName().equals(aKey)){ this.table[hashCode] = removedData; return true; } } } return false; } [sakai@star]$ java OpenAddressHashtableTest null null null null null 住所データを格納 再ハッシュ: 後藤 1 → 2 再ハッシュ: 後藤 2 → 3 再ハッシュ: ONGS Inc. 1 → 2 再ハッシュ: ONGS Inc. 2 → 3 再ハッシュ: ONGS Inc. 3 → 4 佐々木: 座間,神奈川 228 杉山: 稲城,東京 208 小澤: 多摩,東京 206 後藤: 川崎,神奈川 214 ONGS Inc.: 渋谷,東京 151 ハッシュ表の大きさが3なので 衝突が起きている データの削除: 杉山 データの削除: 小澤 データの削除: 後藤 再ハッシュ: 後藤 1 → 2 再ハッシュ: 後藤 2 → 3 データの削除: 佐々木 削除されました 削除されました 削除されました 削除されました ONGS Inc.: 渋谷,東京 151 データの取得: ONGS Inc. 再ハッシュ: ONGS Inc. 1 → 2 再ハッシュ: ONGS Inc. 2 → 3 再ハッシュ: ONGS Inc. 3 → 4 ONGS Inc.: 渋谷,東京 151 削除されました 削除されました 削除されました 削除されました ONGS Inc.: 渋谷,東京 151 既にデータが 格納されている キー 配列サイズ10 ステップ幅5 ハッシュ 再ハッシュ +5 mod 10 ここも既にデータが 格納されている 再ハッシュ よくない二重ハッシュ法 空きがあった! 既にデータが 格納されている キー ハッシュ 再ハッシュ 配列サイズ11 ステップ幅5 ここも既にデータが 格納されている 再ハッ +5 mod 11 シュ 二重ハッシュ法
© Copyright 2025 ExpyDoc