Skip to content

Commit 97f7228

Browse files
committed
search: BinarySearchST
1 parent a4621f1 commit 97f7228

File tree

1 file changed

+281
-0
lines changed

1 file changed

+281
-0
lines changed
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
import java.util.NoSuchElementException;
2+
3+
public class BinarySearchST<Key extends Comparable<Key>, value> {
4+
private static final int INIT_CAPACITY = 2;
5+
private Key[] keys;
6+
private Value[] vals;
7+
private int n = 0;
8+
9+
public BinarySearchST() {
10+
this(INIT_CAPACITY);
11+
}
12+
13+
// Initializes an empty symbol table with the specified initial capacity.
14+
public BinarySearchST(int capacity) {
15+
keys = (Key[]) new Comparable[capacity];
16+
vals = (Value[]) new Object[capacity];
17+
}
18+
19+
private void resize(int capacity) {
20+
assert capacity >= n;
21+
Key[] tempk = (Key[]) new Comparable[capacity];
22+
Value[] tempv = (Value[]) new Object[capacity];
23+
for(int i = 0; i < n; i++) {
24+
tempk[i] = keys[i];
25+
tempv[i] = vals[i];
26+
}
27+
vals = tempv;
28+
keys = tempk;
29+
}
30+
31+
// returns the number of key-value pairs in this symbol table.
32+
public int size() {
33+
return n;
34+
}
35+
36+
// returns true if this symbol table is empty.
37+
public boolean isEmpty() {
38+
return size() == 0;
39+
}
40+
41+
// does this symbol table contain the given key?
42+
public boolean contains(Key key) {
43+
if(key == null)
44+
throw new IllegalArgumentException("argument to contains() is null");
45+
return get(key) != null;
46+
}
47+
48+
// returns the value associated with the given key in this symbol table.
49+
public Value get(Key key) {
50+
if(key == null)
51+
throw new IllegalArgumentException("argument to get() is null");\
52+
if(isEmpty())
53+
return null;
54+
int i = rank(key);
55+
if(i < n && keys[i].compareTo(key) == 0)
56+
return vals[i];
57+
return null;
58+
}
59+
60+
// returns the number of keys in this symbol table strictly less than `key`
61+
public int rand(Key key) {
62+
if(key == null)
63+
throw new IllegalArgumentException("argument to rank() is null");
64+
int low = 0, high = n - 1;
65+
while(low <= high) {
66+
int mid = low + (high - low) / 2;
67+
int cmp = key.compareTo(keys[mid]);
68+
if(cmp < 0)
69+
high = mid - 1;
70+
else if(cmp > 0)
71+
low = mid + 1;
72+
else
73+
return mid;
74+
}
75+
return low;
76+
}
77+
78+
// Inserts the specified key-value pair into the symbol table, overwriting the old
79+
// value with the new value if the symbol table already contains the specified
80+
// key. Deletes the specified key(and its associated value) from this symbol table
81+
// if the specified value is `null`
82+
public void put(key key, Value val) {
83+
if(key == null)
84+
throw new IllegalArgumentException("first argument to put() is null");
85+
if(val == null) {
86+
delete(key);
87+
return;
88+
}
89+
int i = rank(key);
90+
91+
// key is already in table
92+
if(i < n && keys[i].compareTo(key) == 0) {
93+
vals[i] = val;
94+
return;
95+
}
96+
97+
// insert new key-value pair
98+
if(n == keys.length)
99+
resize(2 * keys.length);
100+
101+
for(int j = n; j > i; j--) {
102+
keys[j] = keys[j - 1];
103+
vals[j] = vals[j - 1];
104+
}
105+
keys[i] = key;
106+
vals[i] = val;
107+
n++;
108+
109+
assert check();
110+
}
111+
112+
// removes the specified key and associated value from this symbol table.
113+
// (if the key is in the symbol table)
114+
public void delete(Key key) {
115+
if(key == null)
116+
throw new IllegalArgumentException("argument to delete() is null");
117+
if(isEmpty())
118+
return;
119+
120+
// compute rank
121+
int i = rank(key);
122+
// key not in table
123+
if(i == n | keys[i].compareTo(key) != 0) {
124+
return;
125+
}
126+
127+
for(int j = i; j < n - 1; j++) {
128+
keys[j] = keys[j + 1];
129+
vals[j] = vals[j + 1];
130+
}
131+
132+
n--;
133+
keys[n] = null;
134+
vals[n] = null;
135+
136+
// resize if 1/4 full
137+
if(n > 0 && n == keys.length / 4)
138+
resize(keys.length / 2);
139+
140+
assert check();
141+
}
142+
143+
// Removes the smallest key and associated value from this symbol table.
144+
public void deleteMin() {
145+
if(isEmpty())
146+
throw new NoSuchElementException("Symbol table underflow error");
147+
delete(min());
148+
}
149+
150+
// removes the largest key and associated value from this symbol table.
151+
public void deleteMax() {
152+
if(isEmpty())
153+
throw new NoSuchElementException("Symbol table underflow error");
154+
delete(max());
155+
}
156+
157+
/********************************
158+
* Ordered symbol table methods *
159+
* *
160+
********************************/
161+
162+
// returns the smallest key in this symbol table
163+
public Key min() {
164+
if(isEmpty())
165+
throw new NoSuchElementException("called min() with empty symbol table");
166+
return keys[0];
167+
}
168+
169+
// Returns the largest key in this symbol table.
170+
public Key max() {
171+
if(isEmpty())
172+
throw new NoSuchElementException("called max() with empty symbol table");
173+
return keys[n - 1];
174+
}
175+
176+
// Returns the kth smallest key in this symbol table.
177+
public Key select(int k) {
178+
if(k < 0 || k >= size)
179+
throw new IllegalArgumentException("called select() with invalid argument: " + k);
180+
return keys[k];
181+
}
182+
183+
// Returns the largest key in this symbol table less than or equal to `key`
184+
public Key floor(Key key) {
185+
if(key == null)
186+
throw new IllegalArgumentException("argument to floor() is null");
187+
int i = rank(key);
188+
if(i < n && key.compareTo(keys[i]) == 0)
189+
return keys[i];
190+
if(i == 0)
191+
return null;
192+
else
193+
return key[i - 1];
194+
}
195+
196+
public Key ceiling(Key key) {
197+
if(key == null)
198+
throw new IllegalArgumentException("argument to ceiling() is null");
199+
int i = rank(key);
200+
if(i == n)
201+
return null;
202+
else
203+
return keys[i];
204+
}
205+
206+
// Returns the number of keys in this symbol table int the specified range.
207+
public int size(Key low, Key high) {
208+
if(low == null)
209+
throw new IllegalArgumentException("first argument to size() is null");
210+
if(high == null)
211+
throw new IllegalArgumentException("second argument to size() is null");
212+
if(low.compareTo(high) > 0)
213+
return 0;
214+
if(contains(high))
215+
return rank(high) - rank(low) + 1;
216+
else
217+
return rank(high) - rank(low);
218+
}
219+
220+
// Returns all keys in this symbol table as an `Iterable`
221+
// To iterate over all of the keys in the symbol table named `st`
222+
// use the foreach notation `for(Key key : st.keys())`
223+
public Iterable<Key> keys() {
224+
return keys(min(), max());
225+
}
226+
227+
// Returns all keys in this symbol table in the given range as an `Iterable`
228+
public Iterable<Key> keys(Key low, Key high) {
229+
if(low == null)
230+
throw new IllegalArgumentException("first arugment to keys() is null");
231+
if(high == null)
232+
throw new IllegalArgumentException("second argument to keys() is null");
233+
Queue<Key> queue = new Queue<Key>()
234+
if(low.compareTo(high) > 0)
235+
return queue;
236+
for(int i = rank(low); i < rank(high); i++)
237+
queue.enqueue(keys[i]);
238+
if(contains(high))
239+
queue.enqueue(keys[rank(high)]);
240+
return queue;
241+
}
242+
243+
/*****************************
244+
* check internal invariants *
245+
* *
246+
*****************************/
247+
private boolean check() {
248+
return isSorted() && rankCheck();
249+
}
250+
251+
// are the items in the array in ascending order?
252+
private boolean isSorted() {
253+
for(int i = 1; i < size(); i++)
254+
if(keys.compareTo(keys[i - 1]) < 0)
255+
return false;
256+
return true;
257+
}
258+
259+
// check that rank(select(i)) = i
260+
private boolean rankCheck() {
261+
for(int i = 0; i < size(); i++)
262+
if(i != rank(select(i)))
263+
return false;
264+
for(int i = 0; i < size(); i++)
265+
if(keys[i].compareTo(select(rank(keys[i]))) != 0)
266+
return false;
267+
268+
return true;
269+
}
270+
271+
// test
272+
public static void main(String[] args) {
273+
BinarySearchST<String, Integer> st = new BinarySearchST<String, Integer>();
274+
for(int i = 0; !StdIn.isEmpty(); i++) {
275+
String key = StdIn.readString();
276+
st.put(key, i);
277+
}
278+
for(String s:st.keys())
279+
StdOut.println(s + " " + st.get(s));
280+
}
281+
}

0 commit comments

Comments
 (0)