第13回 ハッシュテーブルを使ったプログラム ~高速に検索するには?~.

Slides:



Advertisements
Similar presentations
【事例演習5】  字句解析     解 説  “ハッシュを用いた字句解析の方法”.
Advertisements

アルゴリズムとデータ構造 2013年6月18日
アルゴリズムとデータ構造1 2005年7月8日
~手続き指向からオブジェクト指向へ(Ⅰ)~
アルゴリズムとデータ構造 2010年7月5日
Ex8. Search for Vacuum Problem(2)
第9回 並び替えアルゴリズム ~さまざまなアルゴリズムを比較しよう~.
アルゴリズムとデータ構造 2012年6月14日
情報工学概論 (アルゴリズムとデータ構造)
独習Java ・ 10.6  Hashtableクラス ・ 10.7  String Tokenizerクラス  12月12日    小笠原 一恵.
アルゴリズムとデータ構造 2011年6月13日
データ構造と アルゴリズム 第八回 知能情報学部 新田直也.
第20章 Flyweight ~同じものを共有して無駄をなくす~
大岩 元 慶応大学環境情報学部 二分木 データ構造とプログラミング(10) 大岩 元 慶応大学環境情報学部
オブジェクト指向入門.
アルゴリズムとデータ構造 2011年6月14日
アルゴリズムとデータ構造 2011年6月20日
データ構造と アルゴリズム 第十一回 理工学部 情報システム工学科 新田直也.
データ構造と アルゴリズム 第四回 知能情報学部 新田直也.
~手続き指向からオブジェクト指向へ[Ⅱ]~
第11回 アプリケーションの構成 ~CUI自動販売機の完成!~.
11.6 ランダムアクセスファイル 11.7 StreamTokenizerクラス
ハッシュテーブル.
ハッシュ表 データ構造とプログラミング(12)
アルゴリズムとデータ構造 2012年6月28日
アルゴリズムとデータ構造 2011年6月27日
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
シューティングゲーム.
アルゴリズムとデータ構造1 2006年7月4日
アルゴリズムとデータ構造1 2006年6月16日
アルゴリズムとデータ構造1 2005年7月15日
アルゴリズムとデータ構造勉強会 第6回 スレッド木
オブジェクト指向 プログラミング 第七回 知能情報学部 新田直也.
アルゴリズムとデータ構造1 2005年7月1日
オブジェクト指向言語論 第八回 知能情報学部 新田直也.
データ構造と アルゴリズム 第五回 知能情報学部 新田直也.
Cプログラミング演習 第10回 二分探索木.
アルゴリズムとデータ構造1 2009年7月9日
アルゴリズムとデータ構造1 2005年7月5日
アルゴリズムとデータ構造1 2005年6月24日
アルゴリズムとデータ構造 2010年6月21日
2005年度 データ構造とアルゴリズム 第6回 「ハッシュ法を用いた探索」
アルゴリズムとデータ構造 2010年7月26日
オブジェクト指向 プログラミング 第六回 知能情報学部 新田直也.
プログラミング 4 探索と計算量.
オブジェクト・プログラミング 第8回.
実装編②HashTable,JavaAPI
アルゴリズムとプログラミング (Algorithms and Programming)
データ構造とアルゴリズム (第5回) 静岡大学工学部 安藤和敏
アルゴリズムとデータ構造1 2006年7月4日
アルゴリズムとデータ構造 2012年6月11日
JAVA入門③ 配列とコレクション.
アルゴリズムとプログラミング (Algorithms and Programming)
コレクション・フレームワーク J2EE I (データベース論) 第6回 /
コレクション・フレームワーク データベース論 第7回.
アルゴリズムとデータ構造1 2008年7月24日
アルゴリズムとデータ構造 2011年6月28日
サブゼミ第7回 実装編① オブジェクト型とキャスト.
第8回 データを収納する (スタックとキュー)
アルゴリズムとデータ構造1 2006年6月23日
アルゴリズムとデータ構造 2013年7月1日
アルゴリズムとデータ構造1 2009年7月2日
第11回放送授業.
アルゴリズムとデータ構造 2012年6月21日
データ構造と アルゴリズム 第四回 知能情報学部 新田直也.
アルゴリズムとデータ構造1 2005年7月12日
アルゴリズムとデータ構造1 2007年7月6日
オブジェクト指向 プログラミング 第六回 知能情報学部 新田直也.
TList リスト構造とは? 複数のデータを扱うために、 データの内容と、次のデータへのポインタを持つ構造体を使う。
オブジェクト・プログラミング 第10回 オブジェクト指向設計のキモ.
Presentation transcript:

第13回 ハッシュテーブルを使ったプログラム ~高速に検索するには?~

学習目標 ハッシュテーブルの概念を説明できる ハッシュテーブルを実装できる ハッシュテーブルの利点・欠点を説明できる 検索におけるkeyとvalueの関係を説明できる 簡単なハッシュテーブルの仕組みを説明できる ハッシュテーブルを実装できる 汎用的なハッシュテーブルを実装できる

13.1 ハッシュテーブルとは 13.1.1 検索と効率 13.1.2 ハッシュテーブル概要 13.1.3 keyとvalue

13.1.1 検索と効率 リニアサーチ O(N) バイナリサーチ O(logN) ハッシュテーブル→ O(1)

13.1.2 ハッシュテーブル概要 配列の番地にそのまま入れておけば、直接検索できる 商品番号1001のコーラは配列の1001番地に入れておく 配列番号 インスタンス 1 2 3 1000 1001 コーラ 1002 1003 ・・・・・

13.1.3 keyとvalue key value key value 検索するためのキー 格納されている値 1001 colaObject 1002 sodaObject 1003 chaObject 1004 ddObject

13.2 ハッシュテーブルの仕組み 13.2.1 名前をキーに検索できるようにする 13.2.2 ハッシュ値を求める 13.2.3 番地の衝突を回避する 13.2.4 ハッシュテーブルの利点・欠点

13.2.1 名前をキー に検索できるようにする key value 名前をキーにしよう Idで商品種類を扱うのはややこしい ハッシュテーブルは文字列のキーが得意 key value ”コーラ” colaObject ”ソーダ” sodaObject ”お茶” chaObject ”DD” ddObject

13.2.2 ハッシュ値を求める ①名前を数字に変換する ②配列の番号と対応させる ③小さい配列で済むようにするには

①名前を数字に変換する インデックシング 文字として扱っている間は、コンピュータでは検索できないので、何らかの数字に変換する 例えば、こんなやり方があります(詳しくは専門書を参照) 変換表 コ 98 コーラ    → 9810367 - 103 ラ 67

もちろんStringクラスもObjectクラスを継承しているよ Javaでハッシュ値を求める JavaではObjectクラスにhashcode()メソッドがあるので、どんなオブジェクトでも、簡単に求めることができます もちろんStringクラスもObjectクラスを継承しているよ String cola = "コーラ"; int hashCode = cola.hashCode();

②配列の番号と対応させる 例えば、コーラを9810367という数字に変換したら対応する配列の番地に挿入する こうしておけば、1回で検索できる 1 2 3 4 9810366 9810367 コーラ 9810368 9810369 ・・・・・ しかし、そんなに大きな配列を作るのは無駄

③小さい配列で 済むようにするには 例えば1000要素の配列で済ませることを考える 1000で割ったあまりを求める コーラ    → 9810367    →    367 1 2 3 4 366 367 コーラ 368 369 ・・・・・ ・・・・・

13.2.3 番地の衝突を回避する ①番地の衝突 ②衝突回避(1):空き番地法 ③空き番地法の問題点 ④衝突回避(2):分離連鎖法

①番地の衝突 違うオブジェクトが同じハッシュ値になる可能性がある コーラ → 31256448 → 448 コーラ    → 31256448    →    448 ソーダ   → 587648448    →    448

②衝突回避(1):空き番地法 もし計算された番地にすでにデータが格納されていた場合次の番地にデータを格納する 次も格納されていたらさらに次の番地に格納しようとする 検索するときにはハッシュ値を求めた後、その番地から順に配列の中身をリニアサーチで調べる ソーダも入りたい! 1 2 3 4 447 448 コーラ 449 ソーダ 500 DDレモン ・・・・・

空き番地法のリスト(追加) 例題13-1 (ItemTypeList.java) #add //新たに商品種類を追加する //配列がいっぱいではないと信じる //同じkeyが存在していないことを信じる public void add(ItemType value){ String key = value.getName(); //商品名をキーとする //ハッシュ値を求める int hashCode = key.hashCode(); int arrayLoc = hashCode % ARRAY_SIZE; //ハッシュした番地から、空のセルを探す while(true){ if(itemTypeArray[arrayLoc] == null){//空のセルがあった itemTypeArray[arrayLoc] = value;//空のセルに商品種類を追加する return; } //空のセルがなかったら arrayLoc++;//次の項目へ if(arrayLoc >= ARRAY_SIZE ){//必要ならラップアラウンド arrayLoc = 0; 例題13-1 (ItemTypeList.java) #add

空き番地法のリスト(検索) 例題13-1 (ItemTypeList.java) #search //商品種類を商品名をキーに検索する public ItemType search(String key){ //ハッシュ値を求める int hashCode = key.hashCode(); int arrayLoc = hashCode % ARRAY_SIZE; //空のセルになるまで順番に探す while(itemTypeArray[arrayLoc] != null){ if(itemTypeArray[arrayLoc].getName().equals(key)){ //Keyが等しい商品が見つかった return itemTypeArray[arrayLoc]; } arrayLoc++;//次の項目へ if(arrayLoc >= ARRAY_SIZE ){//必要ならラップアラウンド arrayLoc = 0; return null;//見つからなかった

③空き番地法の問題点 クラスター化 集中して埋まってしまう個所ができてしまう リニアサーチが長くなって効率が 落ちる 1 2 3 4 5 6 7 8 9 10 11 12 13 リニアサーチが長くなって効率が 落ちる

クラスター化を防ぐ 平方探索 ダブルハッシュ 分離連鎖法 重複した時に、次の番地ではなく1,4,9,16こ先と少し離れた場所に置く 第2種クラスター化 ダブルハッシュ キーの値によって次の番地を決める 分離連鎖法 次に説明する方法

④衝突回避(2):分離連鎖法 衝突したら、その番地からさらに連結リストを使ってデータを格納する 検索するときにはハッシュ値を求めた後、その番地から順に連結リストを使って調べる 1 2 3 4 447 448 コーラ 449 500 ソーダ DDレモン ・・・・・

分離連鎖法のリスト(追加) 例題13-2 (ItemTypeList.java) //同じkeyが存在していないことを信じる public void add(ItemType value){ String key = value.getName();//商品名をキーに設定する //ハッシュ値を求める int hashCode = key.hashCode(); int arrayLoc = hashCode % ARRAY_SIZE; LinkObject insertLink = new LinkObject(value); if (itemTypeLinkArray[arrayLoc] == null){ //ハッシュした番地が未使用だったとき itemTypeLinkArray[arrayLoc] = insertLink;//追加 }else{ //ハッシュした番地が使用済みだったとき LinkObject current = itemTypeLinkArray[arrayLoc];//現在検索中のリンク while (true){ if(current.getNext() == null){ //連結リストの最後が見つかった current.setNext(insertLink); break; //次のリンクを検索中のリンクに設定 current = current.getNext(); } 例題13-2 (ItemTypeList.java)

分離連鎖法のリスト(検索) 例題13-2 (ItemTypeList.java) #search //商品種類を商品名をキーにして検索する public ItemType search(String key){ //ハッシュ値を求める int hashCode = key.hashCode(); int arrayLoc = hashCode % ARRAY_SIZE; LinkObject current = itemTypeLinkArray[arrayLoc];//現在検索中のリンク while (current != null){ //ハッシュした番地に調査していないリンクオブジェクトが残っている if(current.getValue().getName().equals(key)){ //検索対象が見つかった return current.getValue(); }else{ //次のリンクを検索中のリンクに設定 current = current.getNext(); } //ハッシュした番地にリンクオブジェクトがなかったとき return null;//見つからなかった 例題13-2 (ItemTypeList.java) #search

13.2.4 ハッシュテーブルの利点・欠点 考えてみよう

ハッシュテーブルの利点・欠点 利点 欠点 検索が速い → O(1) 名前でも速く検索できる あるキーによる検索しかできない バイナリサーチでも工夫すればできる 欠点 あるキーによる検索しかできない 名前をキーにしたら、idでの検索はリニアサーチ データの保持に内部的には配列を使用するので、事前に用意した配列が満杯に近づいてくると検索、挿入の効率が格段に落ちる 保持するデータを昇順や降順にソートして取り出すといった機能はない

13.3 汎用的なハッシュテーブル 13.3.1 汎用的なハッシュテーブルの実装 13.3.2 JavaAPIを利用する

13.3.1 汎用的な ハッシュテーブルの実装 第12回で作った汎用的なListのように汎用的なハッシュテーブルを作ることを考える 分離連鎖法で実装する

ObjectHashTable インターフェイス void put(Object key,Object value) keyとvalueの組を追加する Object get(Object key) 与えられたkeyで検索する void remove(Object key) 与えられたkeyとvalueの組を削除する Object[] keys() displayメソッドのために、すべてのキーを取得する

ハッシュテーブルのリスト /** * 連結リストオブジェクトクラス */ public class LinkObject { private Object key; //キー private Object value; //値 private LinkObject next; //次の要素への参照 * コンストラクタ public LinkObject(Object newKey,Object newValue){ key = newKey; value = newValue; }  …続く 例題13-3 (LinkObject.java)

(ObjectHashTable.java) ハッシュテーブルのリスト(追加) //キーと値のペアをハッシュテーブルに格納する public void put(Object key,Object value){ //ハッシュ値を求める int hashCode = key.hashCode(); int arrayLoc = hashCode % ARRAY_SIZE; //追加する LinkObject insertLink = new LinkObject(key,value); if (itemTypeLinkArray[arrayLoc] == null){ //ハッシュした番地が未使用だったとき->そのまま追加 itemTypeLinkArray[arrayLoc] = insertLink; size++;//追加したのでHashTableのサイズを一つ増やす return; }else{ //ハッシュした番地が使用済みだったとき->連結リストに追加 LinkObject current = itemTypeLinkArray[arrayLoc];//現在検索中のリンクを設定する //連結リストの最後を探す while (true){ if(current.getNext() == null){ //連結リストの最後が見つかった current.setNext(insertLink);//最後に連結する return;//連結完了 //見つからない current = current.getNext();//次のリンクを検索中のリンクに設定 } 例題13-3 (ObjectHashTable.java) #add

13.3.2 JavaAPIを利用する ハッシュテーブルも良く使われるので、用意されている keyとvalueでデータを格納する クラスのインターフェイス Hashtableを使ってMapを実装 したクラス (実は、Hashtableを使わなくても keyとvalueでデータを格納する方法がある)

MapクラスのAPI ObjectHashtableと同じメソッド ObjectHashtableと異なるメソッド void put(Object key,Object value) Object get(Object key) void remove(Object key) ObjectHashtableと異なるメソッド Set keySet() すべてのキーをSetというインターフェイスで取得する Setとは重複のないListのこと 得られたSetに対し、toArray()を呼べばObjectHashtableと同様の配列が得られる Map map = new HashMap(); Object keys[] = map.keySet().toArray();