Subversion Repositories programming

Rev

Rev 6 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6 Rev 7
Line 2... Line 2...
2
 
2
 
3
import java.io.*;
3
import java.io.*;
4
import java.util.*;
4
import java.util.*;
5
 
5
 
6
public class HashTable implements Map {  // open addressing
6
public class HashTable implements Map {  // open addressing
7
    private Entry[] entries;
7
    private Entry[] entries; 
-
 
8
    
-
 
9
    //size is the total number of elements, including NIL
-
 
10
    //used is the total number of elements, NOT INCLUDING NIL
8
    private int size, used;
11
    private int size, used;
9
    private float loadFactor;
12
    private float loadFactor;
10
    private final Entry NIL = new Entry(null,null);  // dummy
13
    private final Entry NIL = new Entry(null,null);  // dummy
-
 
14
    private int collisions; //initialized to 0 by default
11
 
15
 
-
 
16
    //create a HashTable with a certain capacity (maximum items)
-
 
17
    //and a maximum load factor (if we exceed this we will rehash)
12
    public HashTable(int capacity, float loadFactor) {
18
    public HashTable(int capacity, float loadFactor) {
13
        entries = new Entry[capacity];
19
        entries = new Entry[capacity];
14
        this.loadFactor = loadFactor; }
20
        this.loadFactor = loadFactor; }
15
 
21
 
-
 
22
    //create a HashTable with a certain capacity (maximum items)
-
 
23
    //and a default load factor of 0.75
16
    public HashTable(int capacity) {
24
    public HashTable(int capacity) {
17
        this(capacity,0.75F);}
25
        this(capacity,0.75F);} //calls the HashTable( int, float ) constructor
18
 
26
 
-
 
27
    //create a default HashTable with default capacity (101 items) and
-
 
28
    //default load factor of 0.75
19
    public HashTable() {
29
    public HashTable() {
20
        this(101); }
30
        this(101); } //calls the HashTable( int ) constructor
21
 
31
 
-
 
32
    //Method to find a certain key in the HashTable
-
 
33
    //Precondition: key != null
-
 
34
    //Postcondition: return the entry's value if the key is found
-
 
35
    //               otherwise return null for not found
22
    public Object get(Object key) {
36
    public Object get(Object key) {
23
        int h=hash(key);
37
        int h=hash(key);
24
        for (int i=0; i<entries.length; i++) {
38
        for (int i=0; i<entries.length; i++) {
25
            int j = nextProbe(h,i);
39
            int j = nextProbe(h,i);
26
            Entry entry=entries[j];
40
            Entry entry=entries[j];
Line 29... Line 43...
29
            if (entry.key.equals(key)) return entry.value;  // success
43
            if (entry.key.equals(key)) return entry.value;  // success
30
        }
44
        }
31
        return null;  // failure: key not found
45
        return null;  // failure: key not found
32
    }
46
    }
33
    
47
    
-
 
48
    //Method to add a key/value pair to the HashTable
-
 
49
    //Key - the value that gets hash() called on it. Should be unique (hopefully)
-
 
50
    //Value - the actual data that is to be stored.
-
 
51
    //Precondition: key != null
-
 
52
    //Postcondition: return null if the object was inserted sucessfully
-
 
53
    //               return the value that was there if we updated a value
-
 
54
    //               return null if the table overflows (should never happen,
-
 
55
    //               but it is there just in case)
34
    public Object put(Object key, Object value) {
56
    public Object put(Object key, Object value) {
35
        if (used>loadFactor*entries.length) rehash();
57
        if (used>loadFactor*entries.length) rehash();
36
        int h=hash(key);
58
        int h=hash(key); //hash the key
37
        for (int i=0; i<entries.length; i++) {
59
        for (int i=0; i<entries.length; i++) { //run once for each place in the Table
38
            int j = nextProbe(h,i);
60
            int j = nextProbe(h,i); //get the [first, next] place to try putting the value
39
            Entry entry=entries[j];
61
            Entry entry=entries[j]; //get the Entry at j (where we want to put value)
-
 
62
            
-
 
63
	    //if entry[j] == null then we have found a good place to put value!
40
            if (entry==null) {
64
	    if (entry==null) {
41
                entries[j] = new Entry(key,value);
65
                entries[j] = new Entry(key,value);
42
                ++size;
66
                ++size;
43
                ++used;
67
                ++used;
44
                return null;  // insertion success
68
                return null;  // insertion success
45
            }
69
            }
-
 
70
	    
-
 
71
	    //if entry[j] == NIL then we must continue to probe for a new place,
-
 
72
	    //otherwise we will confuse the remove() and get() methods
46
            if (entry==NIL) continue;
73
            if (entry==NIL) continue;
-
 
74
 
-
 
75
	    //if entry[j].key == key then we need to update the record
47
            if (entry.key.equals(key)) {
76
            if (entry.key.equals(key)) {
48
                Object oldValue=entry.value;
77
                Object oldValue=entry.value;
49
                entries[j].value = value;
78
                entries[j].value = value;
50
                return oldValue;  // update success
79
                return oldValue;  // update success
51
            }
80
            }
52
        }
81
        }
53
        return null;  // failure: table overflow
82
        return null;  // failure: table overflow
54
    }
83
    }
55
 
84
 
-
 
85
    //Method to remove a key/value pair from the table.  This will leave a NIL behind
-
 
86
    //Precondition: key != null
-
 
87
    //Postcondition: return the old value if the key was found, then put a NIL in it's place
-
 
88
    //               return null if the key was not found in the table.
56
    public Object remove(Object key) {
89
    public Object remove(Object key) {
57
        int h=hash(key);
90
        int h=hash(key); //hash the key
58
        for (int i=0; i<entries.length; i++) {
91
        for (int i=0; i<entries.length; i++) { //run once for every place in the table
59
            int j = nextProbe(h,i);
92
            int j = nextProbe(h,i); //find the [first, next] place to put the value
60
            Entry entry=entries[j];
93
            Entry entry=entries[j];
-
 
94
 
61
            if (entry==null) break;
95
            if (entry==null) break; //break out of the loop, since the key was not found
62
            if (entry==NIL) continue;
96
            if (entry==NIL) continue; //keep going, since we found a NIL
63
            if (entry.key.equals(key)) {
97
            if (entry.key.equals(key)) { //we found the key we are looking for...
64
                Object oldValue=entry.value;
98
                Object oldValue=entry.value; //save value to return
65
                entries[j] = NIL;
99
                entries[j] = NIL; //replace the value with a NIL
66
                --size;
100
                --size; //decrement size
67
                return oldValue;  // success
101
                return oldValue;  // success
68
            }
102
            }
69
        }
103
        }
70
        return null;  // failure: key not found
104
        return null;  // failure: key not found
71
    }
105
    }
72
 
106
 
-
 
107
    //Method to access private variable size
-
 
108
    //Precondition: none
-
 
109
    //Postcondition: return size
73
    public int size() {
110
    public int size() {
74
        return size;
111
        return size;
75
    }
112
    }
76
 
113
 
-
 
114
    //A private class which will hold a key/value pair
77
    private class Entry {
115
    private class Entry {
78
        Object key, value;
116
        Object key, value;
79
        Entry(Object k, Object v) { key=k; value=v; }
117
        Entry(Object k, Object v) { key=k; value=v; }
80
    }
118
    }
81
 
119
 
-
 
120
    //our implementation of the hash() function. Takes the Object.hashCode() method
-
 
121
    //and chops off the sign bit
-
 
122
    //Precondition: None (we check for key == null)
-
 
123
    //Postcondition: throw an IllegalArgumentException() if the key == null
-
 
124
    //               return an integer hash for the given key
82
    private int hash(Object key) {
125
    private int hash(Object key) {
83
        if (key==null) throw new IllegalArgumentException();
126
        if (key==null) throw new IllegalArgumentException();
84
        return (key.hashCode() & 0x7FFFFFFF) % entries.length;
127
        return (key.hashCode() & 0x7FFFFFFF) % entries.length;
85
    }
128
    }
86
 
129
    
-
 
130
    //Method to implement linear probing
-
 
131
    //Precondition: h != null; i != null
-
 
132
    //Postcondition: return the next place to try and put the value
87
    private int nextProbe(int h, int i) {
133
    private int nextProbe(int h, int i) {
88
        return (h + i)%entries.length;      // Linear Probing
134
        return (h + i)%entries.length;      // Linear Probing
89
    }
135
    }
90
 
136
 
-
 
137
    //Method to rehash the entire table.  This will get rid of NIL's
-
 
138
    //Precondition: none
-
 
139
    //Postcondition: entries will be twice the size plus one (ensures odd size)
-
 
140
    //               all NIL will be gone
-
 
141
    //               all values will be re-hash()ed
91
    private void rehash() {
142
    private void rehash() {
92
        Entry[] oldEntries = entries;
143
        Entry[] oldEntries = entries;
93
        entries = new Entry[2*oldEntries.length+1];
144
        entries = new Entry[2*oldEntries.length+1];
94
        for (int k=0; k<oldEntries.length; k++) {
145
        for (int k=0; k<oldEntries.length; k++) {
95
            Entry entry=oldEntries[k];
146
            Entry entry=oldEntries[k];