Skip to content

Commit c450851

Browse files
committed
update ch3
1 parent 35ddca6 commit c450851

File tree

12 files changed

+1080
-2
lines changed

12 files changed

+1080
-2
lines changed

Diff for: README.md

+9
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,12 @@ Algorithms, 4th edition textbook code (using c++)
4848
| [-](https://algs4.cs.princeton.edu/24pq/index.php#-) | [IndexMinPQ.h](ch2/head/IndexMinPQ.h) | index min heap priority queue | [-](https://algs4.cs.princeton.edu/24pq/index.php#-) | [IndexMaxPQ.h](ch2/head/IndexMaxPQ.h) | index max heap priority queue |
4949
| [-](https://algs4.cs.princeton.edu/24pq/index.php#-) | [Multiway.h](ch2/head/Multiway.h) | multiway merge | [2.7](https://algs4.cs.princeton.edu/24pq/index.php#2.7) | [Heap.h](ch2/head/Heap.h) | heapsort |
5050

51+
## ch3. Searching
52+
53+
| REF | PROGRAM | DESCRIPTION / JAVADOC | REF | PROGRAM | DESCRIPTION / JAVADOC |
54+
| :----------------------------------------------------------: | :-----------------------------------------------------: | :-----------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :--------------------------: |
55+
| [-](https://algs4.cs.princeton.edu/31elementary/index.php#-) | [FrequencyCounter.cpp](ch3/1_FrequencyCounter/main.cpp) | frequency counter | [3.1](https://algs4.cs.princeton.edu/31elementary/index.php#3.1) | [SequentialSearchST.h](ch3/head/SequentialSearchST.h) | sequential search |
56+
| [3.2](https://algs4.cs.princeton.edu/31elementary/index.php#3.2) | [BinarySearchST.h](ch3/head/BinarySearchST.h) | binary search | [3.3](https://algs4.cs.princeton.edu/32bst/index.php#3.3) | [BST.h](ch3/head/BST.h) | binary search tree |
57+
| [3.4](https://algs4.cs.princeton.edu/33balanced/index.php#3.4) | [RedBlackBST.h](ch3/head/RedBlackBST.h) | red-black tree | [3.5](https://algs4.cs.princeton.edu/34hash/index.php#3.5) | [SeparateChainingHashST.h](ch3/head/SeparateChainingHashST.h) | separate chaining hash table |
58+
| [3.6](https://algs4.cs.princeton.edu/34hash/index.php#3.6) | [LinearProbingHashST.h](ch3/head/LinearProbingHashST.h) | linear probing hash table | [-](https://algs4.cs.princeton.edu/35applications/index.php#-) | [ST.h](ch3/head/ST.h) | ordered symbol table |
59+

Diff for: ch3/1_FrequencyCounter/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ project(1_FrequencyCounter)
33

44
set(CMAKE_CXX_STANDARD 14)
55

6-
set(SOURCE_FILES main.cpp ../head/ST.h ../head/SequentialSearchST.h ../head/BinarySearchST.h ../head/BST.h)
6+
set(SOURCE_FILES main.cpp ../head/ST.h ../head/SequentialSearchST.h ../head/BinarySearchST.h ../head/BST.h ../head/RedBlackBST.h ../head/SeparateChainingHashST.h ../head/LinearProbingHashST.h)
77
add_executable(1_FrequencyCounter ${SOURCE_FILES})

Diff for: ch3/5_RedBlackBST/CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
project(5_RedBlackBST)
3+
4+
set(CMAKE_CXX_STANDARD 14)
5+
6+
set(SOURCE_FILES main.cpp ../head/ST.h ../head/SequentialSearchST.h)
7+
add_executable(5_RedBlackBST ${SOURCE_FILES})

Diff for: ch3/5_RedBlackBST/main.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <iostream>
2+
#include <fstream>
3+
#include "../head/RedBlackBST.h"
4+
5+
using namespace std;
6+
7+
int main() {
8+
RedBlackBST<string, int> st;
9+
fstream file("/home/ace/AceDev/C++/algorithm/ch3/data/tinyST.txt");
10+
string key;
11+
int cnt = 0;
12+
// compute frequency counts
13+
while (file >> key) {
14+
st.put(key, cnt);
15+
cnt++;
16+
}
17+
18+
vector<string> mid = st.midOrder();
19+
for (auto a: mid)
20+
cout << a << " " << st.get(a) << endl;
21+
}

Diff for: ch3/6_SeparateChainingHashST/CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
project(6_SeparateChainingHashST)
3+
4+
set(CMAKE_CXX_STANDARD 14)
5+
6+
set(SOURCE_FILES main.cpp ../head/ST.h ../head/SequentialSearchST.h)
7+
add_executable(6_SeparateChainingHashST ${SOURCE_FILES})

Diff for: ch3/6_SeparateChainingHashST/main.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <iostream>
2+
#include <fstream>
3+
#include "../head/SeparateChainingHashST.h"
4+
5+
using namespace std;
6+
7+
int main() {
8+
SeparateChainingHashST<string, int> st;
9+
fstream file("/home/ace/AceDev/C++/algorithm/ch3/data/tinyST.txt");
10+
string key;
11+
int cnt = 0;
12+
// compute frequency counts
13+
while (file >> key) {
14+
st.put(key, cnt);
15+
cnt++;
16+
}
17+
18+
for (auto k: st)
19+
cout << k << " " << st.get(k) << endl;
20+
}

Diff for: ch3/7_LinearProbingHashST/CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
project(7_LinearProbingHashST)
3+
4+
set(CMAKE_CXX_STANDARD 14)
5+
6+
set(SOURCE_FILES main.cpp ../head/ST.h ../head/SequentialSearchST.h)
7+
add_executable(7_LinearProbingHashST ${SOURCE_FILES})

Diff for: ch3/7_LinearProbingHashST/main.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <iostream>
2+
#include <fstream>
3+
#include "../head/LinearProbingHashST.h"
4+
5+
using namespace std;
6+
7+
int main() {
8+
LinearProbingHashST<string, int> st(50);
9+
fstream file("/home/ace/AceDev/C++/algorithm/ch3/data/tinyST.txt");
10+
string key;
11+
int cnt = 0;
12+
// compute frequency counts
13+
while (file >> key) {
14+
st.put(key, cnt);
15+
cnt++;
16+
}
17+
18+
for (auto k: st)
19+
cout << k << " " << st.get(k) << endl;
20+
}

Diff for: ch3/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@ add_subdirectory(1_FrequencyCounter)
99
add_subdirectory(2_SequentialSearchST)
1010
add_subdirectory(3_BinarySearchST)
1111
add_subdirectory(4_BST)
12-
12+
add_subdirectory(5_RedBlackBST)
13+
add_subdirectory(6_SeparateChainingHashST)
14+
add_subdirectory(7_LinearProbingHashST)
1315
add_subdirectory(8_ST)

Diff for: ch3/head/LinearProbingHashST.h

+229
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
#ifndef CH3_LINEARPROBINGHASHST_H
2+
#define CH3_LINEARPROBINGHASHST_H
3+
4+
#include <vector>
5+
#include <stdexcept>
6+
#include <queue>
7+
8+
using std::vector;
9+
using std::runtime_error;
10+
using std::queue;
11+
12+
/**
13+
* The {@code LinearProbingHashST} class represents a symbol table of generic
14+
* key-value pairs.
15+
* It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,
16+
* <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.
17+
* It also provides a <em>keys</em> method for iterating over all of the keys.
18+
* A symbol table implements the <em>associative array</em> abstraction:
19+
* when associating a value with a key that is already in the symbol table,
20+
* the convention is to replace the old value with the new value.
21+
* Unlike {@link java.util.Map}, this class uses the convention that
22+
* values cannot be {@code null}—setting the
23+
* value associated with a key to {@code null} is equivalent to deleting the key
24+
* from the symbol table.
25+
* <p>
26+
* This implementation uses a linear probing hash table. It requires that
27+
* the key type overrides the {@code equals()} and {@code hashCode()} methods.
28+
* The expected time per <em>put</em>, <em>contains</em>, or <em>remove</em>
29+
* operation is constant, subject to the uniform hashing assumption.
30+
* The <em>size</em>, and <em>is-empty</em> operations take constant time.
31+
* Construction takes constant time.
32+
* <p>
33+
* For additional documentation, see <a href="https://algs4.cs.princeton.edu/34hash">Section 3.4</a> of
34+
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
35+
* For other implementations, see {@link ST}, {@link BinarySearchST},
36+
* {@link SequentialSearchST}, {@link BST}, {@link RedBlackBST}, and
37+
* {@link SeparateChainingHashST},
38+
*
39+
* @author Robert Sedgewick
40+
* @author Kevin Wayne
41+
*/
42+
template<typename Key, typename Value>
43+
class LinearProbingHashST {
44+
public:
45+
/**
46+
* Initializes an empty symbol table with the specified initial capacity.
47+
*
48+
* @param capacity the initial capacity
49+
*/
50+
LinearProbingHashST(int capacity) : m(capacity), n(0), keys(capacity), vals(capacity), flags(capacity, true) {}
51+
52+
/**
53+
* Initializes an empty symbol table.
54+
*/
55+
LinearProbingHashST() : LinearProbingHashST(INIT_CAPACITY) {}
56+
57+
/**
58+
* Returns the number of key-value pairs in this symbol table.
59+
*
60+
* @return the number of key-value pairs in this symbol table
61+
*/
62+
int size() {
63+
return n;
64+
}
65+
66+
/**
67+
* Returns true if this symbol table is empty.
68+
*
69+
* @return {@code true} if this symbol table is empty;
70+
* {@code false} otherwise
71+
*/
72+
bool isEmpty() {
73+
return size() == 0;
74+
}
75+
76+
/**
77+
* Returns true if this symbol table contains the specified key.
78+
*
79+
* @param key the key
80+
* @return {@code true} if this symbol table contains {@code key};
81+
* {@code false} otherwise
82+
* @throws IllegalArgumentException if {@code key} is {@code null}
83+
*/
84+
bool contains(Key key) {
85+
for (int i = hash(key); !flags[i]; i = (i + 1) % m)
86+
if (keys[i] == key)
87+
return true;
88+
return false;
89+
}
90+
91+
/**
92+
* Inserts the specified key-value pair into the symbol table, overwriting the old
93+
* value with the new value if the symbol table already contains the specified key.
94+
* Deletes the specified key (and its associated value) from this symbol table
95+
* if the specified value is {@code null}.
96+
*
97+
* @param key the key
98+
* @param val the value
99+
* @throws IllegalArgumentException if {@code key} is {@code null}
100+
*/
101+
void put(Key key, Value val) {
102+
// double table size if 50% full
103+
if (n >= m / 2) resize(2 * m);
104+
105+
int i;
106+
for (i = hash(key); !flags[i]; i = (i + 1) % m) {
107+
if (keys[i] == key) {
108+
vals[i] = val;
109+
return;
110+
}
111+
}
112+
keys[i] = key;
113+
vals[i] = val;
114+
flags[i] = false;
115+
n++;
116+
}
117+
118+
/**
119+
* Returns the value associated with the specified key.
120+
* @param key the key
121+
* @return the value associated with {@code key};
122+
* {@code null} if no such value
123+
* @throws IllegalArgumentException if {@code key} is {@code null}
124+
*/
125+
Value get(Key key) {
126+
for (int i = hash(key); !flags[i]; i = (i + 1) % m)
127+
if (keys[i] == key)
128+
return vals[i];
129+
throw runtime_error("illegal key");
130+
}
131+
132+
/**
133+
* Removes the specified key and its associated value from this symbol table
134+
* (if the key is in this symbol table).
135+
*
136+
* @param key the key
137+
* @throws IllegalArgumentException if {@code key} is {@code null}
138+
*/
139+
void delete_op(Key key) {
140+
if (!contains(key)) return;
141+
142+
// find position i of key
143+
int i = hash(key);
144+
while (key != keys[i]) {
145+
i = (i + 1) % m;
146+
}
147+
148+
// delete key and associated value
149+
flags[i] = true;
150+
151+
// rehash all keys in same cluster
152+
i = (i + 1) % m;
153+
while (!flags[i]) {
154+
// delete keys[i] an vals[i] and reinsert
155+
Key keyToRehash = keys[i];
156+
Value valToRehash = vals[i];
157+
flags[i] = true;
158+
n--;
159+
put(keyToRehash, valToRehash);
160+
i = (i + 1) % m;
161+
}
162+
n--;
163+
// halves size of array if it's 12.5% full or less
164+
if (n > 0 && n <= m / 8) resize(m / 2);
165+
}
166+
167+
private:
168+
class Iterator {
169+
queue<Key> q;
170+
public:
171+
Iterator(vector<Key> &k, vector<bool> &flag, int m) {
172+
for (int i = 0; i < m; ++i) {
173+
if (!flag[i])
174+
q.push(k[i]);
175+
}
176+
}
177+
178+
Key &operator*() {
179+
return q.front();
180+
}
181+
182+
Iterator &operator++() {
183+
q.pop();
184+
return *this;
185+
}
186+
187+
bool operator!=(const Iterator &it) { return !q.empty(); }
188+
};
189+
190+
public:
191+
Iterator begin() { return {keys, flags, m}; };
192+
193+
Iterator end() { return {keys, flags, m}; };
194+
195+
private:
196+
// hash function for keys - returns value between 0 and M-1
197+
int hash(Key key) {
198+
return (std::hash<Key>()(key) & 0x7fffffff) % m;
199+
}
200+
201+
// resizes the hash table to the given capacity by re-hashing all of the keys
202+
void resize(int capacity) {
203+
vector<bool> tf(flags.begin(), flags.end());
204+
int tmp = m;
205+
keys.resize(capacity);
206+
vals.resize(capacity);
207+
flags.resize(capacity);
208+
flags.assign(capacity, true);
209+
m = capacity;
210+
for (int i = 0; i < tmp; ++i) {
211+
if (!tf[i]) {
212+
this->put(keys[i], vals[i]);
213+
}
214+
}
215+
}
216+
217+
private:
218+
static int INIT_CAPACITY;
219+
int n; // number of key-value pairs in the symbol table
220+
int m; // size of linear probing table
221+
vector<Key> keys; // the keys
222+
vector<Value> vals; // the values
223+
vector<bool> flags; // to tell whether this position is "usable"
224+
};
225+
226+
template<typename Key, typename Value>
227+
int LinearProbingHashST<Key, Value>::INIT_CAPACITY = 4;
228+
229+
#endif //CH3_LINEARPROBINGHASHST_H

0 commit comments

Comments
 (0)