ソフトウエア基礎
ohmi@rsch.tuis.ac.jp

ハッシュ法(3) 解答例

課題hash-17

deleteメソッドを呼ぶ直前と直後に、dump_hashtableメソッドを呼ぶと 以下のような結果が出力される。

0:
1:
2:
3:xyz
4:abc
5:yyy
6:
7:
8:
9:

0:
1:
2:
3:DELETED
4:abc
5:yyy
6:
7:
8:
9:
0:

1:
2:
3:zyx
4:abc
5:yyy
6:bbb
7:
8:
9:

ハッシュ表の3にxyzが格納されていたのが、削除することで、DELETEDに変え られ、その後、zyxが格納されていることが分かる。

ハッシュ表の中で一度削除した部分に再び違うデータが格納される例を考え る課題:
例えば、runメソッド内に以下のように記述する。

	set("fff");
	set("efg");
	dump_hashtable();
	delete("fff");
	dump_hashtable();
	set("feg");
	dump_hashtable();

実行すると以下のような結果を得る(5〜8のみ示す)。

5:
6:fff
7:efg
8:

5:
6:DELETED
7:efg
8:

5:
6:feg
7:efg
8:

課題hash-18

runメソッド内に以下のように記述する。

	set("fff");
	dump_hashtable();
	delete("fff");
	set("DELETED");
	dump_hashtable();
	set("feg");
	set("yyy");
	dump_hashtable();

実行すると以下のような結果を得る(3〜7のみ示す)。

3:
4:
5:
6:fff
7:

3:DELETED
4:
5:
6:DELETED
7:

3:DELETED
4:yyy
5:
6:feg
7:

まず、fffはハッシュ表の6に格納された。次にfffを削除し、ハッシュ表の 6に削除を示すDELETED(変数deletedの値)が格納された。文字列DELETEDの ハッシュ値は3となり、ハッシュ表の3に格納された。 次にfegをハッシュ表に格納しようとすると、ハッシュ値である6の場所には、 削除を示すDELETEDが入っており、そこにfegが格納された。 yyyを格納しようとすると、ハッシュ値である3の場所には、set("DELETED") で格納した文字列データが入っており、そこには格納されず、その1つ下の 4にyyyが格納された。このように、削除を示すDELETEDと、set("DELETED") でハッシュ表に格納したデータが区別されていることが分かる。

課題hash-19

HashData.java
public class HashData {
    public String key;
    public String name;
    public int math;
    public int english;
    public String email;
}
Hash5.java
public class Hash5 {
    final int size = 10;
    HashData hashtable[] = new HashData[size];
    String deleted = new String("DELETED");
    //    String deleted = new String("DELETED");
    public static void main(String args[]) {
	Hash5 s = new Hash5();
	s.run();
    }

    public void run() {
	// ハッシュ表をクリア(全部null)
	for(int i = 0; i < hashtable.length; i++) {
	    hashtable[i] = null;
	}

	set("s03881", "山田太郎", 80, 85, "yamada@hogehoge.example"); 
	set("s03872", "松田二郎", 70, 87, "matsuda@hogehoge.example"); 

	dump_hashtable(); // ハッシュ表の内容を表示する

	print_exist("s03881"); // "abc"というデータは存在するか?
	print_exist("s03882"); // "abc"というデータは存在するか?
    }

    int hash(String key) {
	int s = 0;
	for (int i = 0; i < key.length(); i++) {
	    s += key.charAt(i);
	}
	return s % size;
    }
    void set(String key, String name, int math, int english, String email) {
	int hashcode = hash(key);
	HashData d = new HashData();
	d.key = key;
	d.name = name;
	d.math = math;
	d.english = english;
	d.email = email;
	while(hashtable[hashcode] != null &&
	      hashtable[hashcode].key != deleted) {
	    hashcode++;
	}
	hashtable[hashcode] = d;
    }
    boolean delete(String key) {
	int hashcode = hash(key);
	while(hashtable[hashcode] != null) {
	    if (hashtable[hashcode].key == key) {
		hashtable[hashcode].key = deleted;
		return true;
	    }
	    hashcode++;
	}
	return false;
    }
    void print_exist(String key) {
	int hashcode = hash(key);
	while(hashtable[hashcode] != null) {
	    HashData d = hashtable[hashcode];
	    if (d.key == key) {
		System.out.println(key + "は存在します" +
				 "(" + d.key + "," + d.name + "," +
				 d.math +"," + d.english + "," + d.email + ")");
		return;
	    }
	    hashcode++;
	}
	System.out.println(key + "は存在しません");
    }
    void dump_hashtable() {
	for (int i = 0; i < hashtable.length; i++) {
	    System.out.print(i + ":");
	    HashData d = hashtable[i];
	    if (d == null) {
		System.out.println();
	    } else {
		System.out.println(d.key + "," + d.name + "," +
				   d.math +"," + d.english + "," + d.email);
	    }
	}
    }
}

課題hash-20

HashData.java
public class HashData {
    private String key;
    private String name;
    private int math;
    private int english;

    public String getKey() { return key; }
    public String getName() { return name; }
    public int getMath() { return math; }
    public int getEnglish() { return english; }

    public void setKey(String k) { key = k; }
    public void setName(String n) { name = n; }
    public void setMath(int m) { math = m; }
    public void setEnglish(int e) { english = e; }
}
Hash5.java
public class Hash5 {
    final int size = 10;
    HashData hashtable[] = new HashData[size];
    String deleted = new String("DELETED");
    //    String deleted = new String("DELETED");
    public static void main(String args[]) {
	Hash5 s = new Hash5();
	s.run();
    }

    public void run() {
	// ハッシュ表をクリア(全部null)
	for(int i = 0; i < hashtable.length; i++) {
	    hashtable[i] = null;
	}

	set("s03881", "山田太郎", 80, 85); 
	set("s03872", "松田二郎", 70, 87); 

	dump_hashtable(); // ハッシュ表の内容を表示する

	print_exist("s03881"); // "abc"というデータは存在するか?
	print_exist("s03882"); // "abc"というデータは存在するか?
    }

    int hash(String key) {
	int s = 0;
	for (int i = 0; i < key.length(); i++) {
	    s += key.charAt(i);
	}
	return s % size;
    }
    void set(String key, String name, int math, int english) {
	int hashcode = hash(key);
	HashData d = new HashData();
	d.setKey(key);
	d.setName(name);
	d.setMath(math);
	d.setEnglish(english);
	while(hashtable[hashcode] != null &&
	      hashtable[hashcode].getKey() != deleted) {
	    hashcode++;
	}
	hashtable[hashcode] = d;
    }
    boolean delete(String key) {
	int hashcode = hash(key);
	while(hashtable[hashcode] != null) {
	    if (hashtable[hashcode].getKey() == key) {
		hashtable[hashcode].setKey(deleted);
		return true;
	    }
	    hashcode++;
	}
	return false;
    }
    void print_exist(String key) {
	int hashcode = hash(key);
	while(hashtable[hashcode] != null) {
	    HashData d = hashtable[hashcode];
	    if (d.getKey() == key) {
		System.out.println(key + "は存在します" +
				 "(" + d.getKey()+ "," + d.getName() + "," +
				 d.getMath() +","+ d.getEnglish() + ")");
		return;
	    }
	    hashcode++;
	}
	System.out.println(key + "は存在しません");
    }
    void dump_hashtable() {
	for (int i = 0; i < hashtable.length; i++) {
	    System.out.print(i + ":");
	    HashData d = hashtable[i];
	    if (d == null) {
		System.out.println();
	    } else {
		System.out.println(d.getKey() + "," + d.getName() + "," +
				   d.getMath() +"," + d.getEnglish());
	    }
	}
    }
}

課題hash-21

HashData.javaに以下のメソッドを追加する。

    public int getTotal() { return math+english; }

また、Hash5.javaのprint_exist,dump_hashtableメソッドを 以下のように修正する。

    void print_exist(String key) {
	int hashcode = hash(key);
	while(hashtable[hashcode] != null) {
	    HashData d = hashtable[hashcode];
	    if (d.getKey() == key) {
		System.out.println(key + "は存在します" +
				 "(" + d.getKey() + "," + d.getName() + "," +
				 d.getMath() +"," + d.getEnglish() +
				 "," + d.getTotal() + ")");
		return;
	    }
	    hashcode++;
	}
	System.out.println(key + "は存在しません");
    }
    void dump_hashtable() {
	for (int i = 0; i < hashtable.length; i++) {
	    System.out.print(i + ":");
	    HashData d = hashtable[i];
	    if (d == null) {
		System.out.println();
	    } else {
		System.out.println(d.getKey() + "," + d.getName() + "," +
				   d.getMath() +"," + d.getEnglish() +"," +
				   d.getTotal());
	    }
	}
    }

課題hash-22

省略
ソフトウエア基礎

ohmi@rsch.tuis.ac.jp

Valid HTML 4.01!