21
1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

  • View
    260

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

1

Hashing Techniques: Implementation

• Implementing Hash Functions

• Implementing Hash Tables

• Implementing Chained Hash Tables

• Implementing Open Hash Tables

Page 2: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

2

Implementing Hash Functions

• Recall that search keys can be letters, strings or structures like records/containers.

• Thus we make the search key as general as possible, of type Object, in our implementation.

• Then, can we simultaneously represent both basic values and objects?

• Define wrappers for the basic values to make the hash function generic.

• Java’s wrapper classes are not adequate for our purpose.

Page 3: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

3

Implementing Hash Functions (cont'd)

• For convenience, we represent our hash function h as the composition of two functions f and g, i.e., h = g o f.

• That is, given f and g and a key k, the hash value of k is:

h(k) = g(f(k)).

• Decomposing h provides a good separation of concern.

• Ideally, f and g should be independent of each other.

• With care, we can design f and g in such a way that the composition h = g o f is a good hash function.

Page 4: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

4

Implementing Hash Functions (cont'd)

• For a set K of keys and the set Z of non-negative integers, we define f :

f: K -> Z

• The function g maps Z into {0,1,…,n-1}:

g: Z -> {0, 1, …, n-1}

• Since Java’s Object class defines a method hashCode(), we can carefully define f to correspond to it.

• Note that the choice of f depends on the characteristics of its domain, the key set K.

Page 5: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

5

Hash Functions with Integral Keys

• The Integral data types in Java are byte, short, int, long and char

• Their underlying implementation can be viewed as integer, and we have:

f (k) = k

• The wrapper class for these types can be written:1 public class Int extends AbstractObject{

2 protected int value;

3 public int hashCode(){

4 return value;

5 }

6}

• In this case the hashCode method simply returns the content of the value field.

Page 6: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

6

Hash Functions with String Keys

• A string in Java is a sequence of characters. There are many ways of defining functions of strings that return integers.

• One way is the folding technique achieved by summing the ASCII values of the characters in a string.

• That is, given a string s = c0c1c2…cn-1 , we have

f(s) = c0 + c1 + c2 + … + cn-1 mod n

• Since f can easily overflow, we use the alternative:

char[0] + (27 * char[1]) + (729 * char[2])mod n

Page 7: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

7

Hash Functions with String Keys (cont'd)

1 public class Str extends AbstractObject {

2 protected String value;

3 private size = value.length();

4 public int hashCode() {

5 int hashVal = 0;

6 return (value.charAt(0) +

7 (27 * value.charAt(1)) +

8 (729 * value.charAt(2))) % size;

9 }

10 }

Page 8: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

8

Implementing Hash Tables: The Hierarchy Tree

MyComparable

Container

SearchableContainer

HashTable

AbstractObject

AbstractContainer

AbstractSearchableContainer

AbstractHashTable

ChainedHashTable

OpenScatterTable

Page 9: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

9

The HashTable Interface• From the introductory sessions, the interface HashTable

extends the SearchableContainer interface.

• It has the following definition:

1 public interface HashTable2 extends SearchableContainer {3 double getLoadFactor();4 }

• HashTable introduces getLoadFactor() which returns the load factor of the hash table.

• An AbstractHashTable is defined from which concrete hash table implementations will result.

Page 10: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

10

The AbstractHashTable Class

1 public abstract class AbstractHashTable

2 extends AbstractSearchableContainer

3 implements HashTable {

5 public abstract int getLength();

7 protected final int f(Object obj) {

8 return obj.hashCode();

9 }

10 protected final int g(int i) {

11 return Math.abs(i) % getLength();

12 }

13 protected final int h(Object obj) {

14 return g(f(obj));

15 }

16 //...

17 }

Page 11: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

11

The ChainedHashTable

1 public class ChainedHashTable2 extends AbstractHashTable {3 protected LinkedList [] array;4 public ChainedHashTable(int size) {5 array = new LinkedList[size];6 for(int j = 0; j < size; j++)7 array[j] = new LinkedList();8 }9 public int getLength() {10 return array.length;11 }12 public void purge() {13 for(int i = 0; i < getLength(); i++)14 array[i].purge();15 super.count = 0;16 }17}

Page 12: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

12

Chained Hash Tables: Insertion & Deletion

1 public class ChainedHashTable2 extends AbstractHashTable {3 protected LinkedList [] array;4 public void insert(Comparable comparable) {5 array[h(comparable)].append(comparable);6 super.count++;7 }8 public void withdraw(Comparable comparable) {9 array[h(comparable)].extract(comparable);10 super.count--;11 }12 }

Page 13: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

13

Chained Hash Tables: Retrieval

1 public class ChainedHashTable extends2 AbstractHashTable {3 protected LinkedList [] array;4 public Comparable find(Comparable comparable){5 for(LinkedList.Element chain =6 array[h(comparable)].getHead();7 chain != null; chain =8 chain.getNext()){9 Comparable comparable1 =10 (Comparable)chain.getDatum();1112 if(comparable.isEQ(comparable1))13 return comparable1;14 }15 return null;16 }17 }

Page 14: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

14

Open Hash Table Implementation

1 public class OpenScatterTable2 extends AbstractHashTable {34 protected Entry array[];5 static final int empty = 0;6 static final int occupied = 1;7 static final int deleted = 2;89 protected static final class Entry {10 int state;11 Comparable object;12 void purge(){ state = 0; object = null;}1314 Entry() {state = 0;}15 }16 }

Page 15: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

15

Open Hash Table: Initialization

1 public class OpenScatterTable2 extends AbstractHashTable {3 protected Entry array[];45 public OpenScatterTable(int size) {67 array = new Entry[size];89 for(int j = 0; j < size; j++)10 array[j] = new Entry();11 }12 public void purge() {13 for(int i = 0; i < getLength(); i++)14 array[i].purge();15 super.count = 0;16 }17 }

Page 16: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

16

Open Hash Tables: Finding Empty Cells

1 public class OpenScatterTable2 extends AbstractHashTable {34 protected static int c(int i) {5 return i;6 }7 protected int findUnoccupied(Object obj) {89 int i = h(obj);1011 for(int j = 0; j < super.count + 1; j++) {12 int k = (i + c(j)) % getLength();13 if(array[k].state != occupied)14 return k;15 }16 throw new ContainerFullException();17 }18}

Page 17: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

17

Open Hash Tables: Insertion

1 public class OpenScatterTable2 extends AbstractHashTable {34 public void insert(Comparable comparable) {56 if(super.count == getLength()) {7 throw new ContainerFullException();8 } else {9 int i = findUnoccupied(comparable);10 array[i].state = occupied;11 array[i].object = comparable;12 super.count++;13 return;14 }15 }16}

Page 18: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

18

Open Hash Tables: Retrieval1 public class OpenScatterTable2 extends AbstractHashTable {3 protected int findMatch(Comparable comparable) {4 int i = h(comparable);5 for(int j = 0; j < getLength(); j++) {6 int k = (i + c(j)) % getLength();7 if(array[k].state == empty) break;8 if(array[k].state == occupied &&9 comparable.isEQ(array[k].object))10 return k;11 }11 return -1;12 }13 public Comparable find(Comparable comparable) {14 int i = findMatch(comparable);15 if(i >= 0) return array[i].object;16 else return null; 17 }18 }

Page 19: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

19

Open Hash Tables: Deletion1 public class OpenScatterTable2 extends AbstractHashTable {34 public void withdraw(Comparable comparable) {5 if(super.count == 0)6 throw new ContainerEmptyException();7 int i = findInstance(comparable);8 if(i < 0) {9 throw 10 new IllegalArgumentException(11 "object not found");12 } else {13 array[i].state = 2;14 array[i].object = null;15 super.count--;16 return;17 }18 }19 }

Page 20: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

20

Review Questions

• Why are the methods f, g and h on Page 9 made final? Would someone not like to override them?

• Compare the insert() method of the ChainedHashTable class and that of OpenScatterTable. Are they both correct?

• How do you modify the findUnoccupied() method and ensure that it is efficient?

• Why is the isEQ() method used in Line 12 of find() on Page 13 instead of Java Object's equals() method?

• The method withdraw() of OpenScatterTable will be very inefficient if there are many deletions. Why?

Page 21: 1 Hashing Techniques: Implementation Implementing Hash Functions Implementing Hash Tables Implementing Chained Hash Tables Implementing Open Hash Tables

21

Exercises1. Why does the Int wrapper class, in particular, extends the

AbstractObject class?

2. Are the wrapper classes Int and Str concrete classes or abstract classes? Why?

3. What does the hashCode() method of Object class return by default? Why do we have to redefine it in our hash table implementation?

4. If the cost of inserting a record r in a hash table is O(1), what is the cost of deleting r?

5. Can the load factor in an open addressed hash table that is efficiently implemented be 1? Explain your answer.

6. In some hashing schemes, table size has no effect on collisions. Explain.