9.14 Lab: Hash ADT
Now that you have a working implementation of the HashNode and HashTable classes, you can convert them to templates, and update main.cpp to match with the new template classes. In order for everything to work you will also have to: - overload the == operator for the Student class - declare the hash function a friend function of the Student class - send the hash function as an argument to insert, remove, and search functions.
This commit is contained in:
parent
b43f08aacc
commit
30ad8892de
@ -4,4 +4,4 @@ project(06_hash_tables)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_executable(06_hash_tables main.cpp
|
||||
HashTable.cpp)
|
||||
Student.cpp)
|
||||
|
@ -1,16 +1,16 @@
|
||||
// Specification file for the HashNode class
|
||||
// Written By: Iurii Tatishchev
|
||||
// Changed by: Iurii Tatishchev
|
||||
|
||||
#ifndef _HASH_NODE
|
||||
#define _HASH_NODE
|
||||
|
||||
#include "Student.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
// To do: convert to a template
|
||||
template<typename T>
|
||||
class HashNode {
|
||||
private:
|
||||
Student item;
|
||||
int occupied; // 1 -> occupied, 0 -> empty
|
||||
T item;
|
||||
int occupied; // 1 -> occupied, 0 -> empty from start, -1 -> empty after removal
|
||||
int noCollisions;
|
||||
|
||||
public:
|
||||
@ -20,27 +20,27 @@ public:
|
||||
noCollisions = 0;
|
||||
}
|
||||
|
||||
HashNode(Student anItem) {
|
||||
HashNode(T anItem) {
|
||||
item = anItem;
|
||||
occupied = 1;
|
||||
noCollisions = 0;
|
||||
}
|
||||
|
||||
HashNode(Student anItem, int ocp, int nCol) {
|
||||
HashNode(T anItem, int ocp, int nCol) {
|
||||
item = anItem;
|
||||
occupied = ocp;
|
||||
noCollisions = nCol;
|
||||
}
|
||||
|
||||
// setters
|
||||
void setItem(const Student &anItem) { item = anItem; }
|
||||
void setItem(const T &anItem) { item = anItem; }
|
||||
|
||||
void setOccupied(int ocp) { occupied = ocp; }
|
||||
|
||||
void setNoCollisions(int nCol) { noCollisions = nCol; }
|
||||
|
||||
// getters
|
||||
Student getItem() const { return item; }
|
||||
T getItem() const { return item; }
|
||||
|
||||
int getOccupied() const { return occupied; }
|
||||
|
||||
|
@ -1,15 +1,17 @@
|
||||
// Specification file for the Hash class
|
||||
// Written By: Iurii Tatishchev
|
||||
// Changed by: Iurii Tatishchev
|
||||
|
||||
|
||||
#ifndef HASHTABLE_H_
|
||||
#define HASHTABLE_H_
|
||||
|
||||
#include "HashNode.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
template<class ItemType>
|
||||
class HashTable {
|
||||
private:
|
||||
HashNode *hashAry;
|
||||
HashNode<ItemType> *hashAry;
|
||||
int hashSize;
|
||||
int count;
|
||||
|
||||
@ -17,13 +19,13 @@ public:
|
||||
HashTable() {
|
||||
count = 0;
|
||||
hashSize = 53;
|
||||
hashAry = new HashNode[hashSize];
|
||||
hashAry = new HashNode<ItemType>[hashSize];
|
||||
}
|
||||
|
||||
HashTable(int n) {
|
||||
count = 0;
|
||||
hashSize = n;
|
||||
hashAry = new HashNode[hashSize];
|
||||
hashAry = new HashNode<ItemType>[hashSize];
|
||||
}
|
||||
|
||||
~HashTable() { delete[] hashAry; }
|
||||
@ -38,14 +40,81 @@ public:
|
||||
|
||||
bool isFull() const { return count == hashSize; }
|
||||
|
||||
bool insert(const Student &itemIn);
|
||||
bool insert(const ItemType &itemIn, int h(const ItemType &key, int size));
|
||||
|
||||
bool remove(Student &itemOut, string key);
|
||||
bool remove(ItemType &itemOut, const ItemType &key, int h(const ItemType &key, int size));
|
||||
|
||||
int search(Student &itemOut, string key) const;
|
||||
|
||||
private:
|
||||
int _hash(string key) const;
|
||||
int search(ItemType &itemOut, const ItemType &key, int h(const ItemType &key, int size)) const;
|
||||
};
|
||||
|
||||
/*~*~*~*
|
||||
Insert an item into the hash table
|
||||
It does not reject duplicates
|
||||
*~**/
|
||||
template<class ItemType>
|
||||
bool HashTable<ItemType>::insert(const ItemType &itemIn, int h(const ItemType &key, int size)) {
|
||||
if (count == hashSize)
|
||||
return false;
|
||||
|
||||
int pos = h(itemIn, hashSize);
|
||||
int collisions = 0;
|
||||
while (hashAry[pos].getOccupied() == 1) {
|
||||
++pos;
|
||||
++collisions;
|
||||
pos = pos % hashSize;
|
||||
}
|
||||
hashAry[pos].setItem(itemIn);
|
||||
hashAry[pos].setOccupied(1);
|
||||
hashAry[pos].setNoCollisions(collisions);
|
||||
count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*~*~*~*
|
||||
Removes the item with the matching key from the hash table
|
||||
if found:
|
||||
- copies data in the hash node to itemOut
|
||||
- replaces data in the hash node with an empty record (occupied = -1: deleted!)
|
||||
- returns true
|
||||
if not found:
|
||||
- returns false
|
||||
*~**/
|
||||
template<class ItemType>
|
||||
bool HashTable<ItemType>::remove(ItemType &itemOut, const ItemType &key, int h(const ItemType &key, int size)) {
|
||||
int pos = h(key, hashSize);
|
||||
for (int collisions = 0; collisions < count; collisions++) {
|
||||
if (hashAry[pos].getOccupied() == 1 && hashAry[pos].getItem() == key) {
|
||||
itemOut = hashAry[pos].getItem();
|
||||
// -1 means freed
|
||||
hashAry[pos].setOccupied(-1);
|
||||
count--;
|
||||
return true;
|
||||
}
|
||||
pos = (pos + 1) % hashSize;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*~*~*~*
|
||||
hash search - linear probe
|
||||
if found:
|
||||
- copy data to itemOut
|
||||
- returns the number of collisions for this key
|
||||
if not found, returns -1
|
||||
*~**/
|
||||
template<class ItemType>
|
||||
int HashTable<ItemType>::search(ItemType &itemOut, const ItemType &key, int h(const ItemType &key, int size)) const {
|
||||
int pos = h(key, hashSize);
|
||||
for (int collisions = 0; collisions < count; collisions++) {
|
||||
if (hashAry[pos].getOccupied() == 0) return -1;
|
||||
if (hashAry[pos].getOccupied() == 1 && hashAry[pos].getItem() == key) {
|
||||
itemOut = hashAry[pos].getItem();
|
||||
return hashAry[pos].getNoCollisions();
|
||||
}
|
||||
pos = (pos + 1) % hashSize;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif // HASHTABLE_H_
|
||||
|
16
06-hash-tables/Student.cpp
Normal file
16
06-hash-tables/Student.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// Implementation file for the Student class
|
||||
// Written By: Iurii Tatishchev
|
||||
|
||||
#include <string>
|
||||
#include "Student.h"
|
||||
|
||||
/*~*~*~*
|
||||
Hash function: takes the key and returns the index in the hash table
|
||||
*~**/
|
||||
int key_to_index(const Student &key, int size) {
|
||||
string k = key.name;
|
||||
int sum = 0;
|
||||
for (int i = 0; k[i]; i++)
|
||||
sum += k[i];
|
||||
return sum % size;
|
||||
};
|
@ -1,10 +1,17 @@
|
||||
// Specification file for the Student class
|
||||
// Modified by: Iurii Tatishchev
|
||||
// IDE: CLion
|
||||
|
||||
#ifndef STUDENT_H
|
||||
#define STUDENT_H
|
||||
|
||||
using std::string;
|
||||
|
||||
class Student; // Forward Declaration
|
||||
|
||||
// Function Prototypes for friend functions
|
||||
int key_to_index(const Student &key, int size);
|
||||
|
||||
class Student {
|
||||
private:
|
||||
double gpa;
|
||||
@ -16,7 +23,7 @@ public:
|
||||
gpa = -1;
|
||||
} // Constructor
|
||||
Student(string n, double g) {
|
||||
name = n;
|
||||
name = n;/* Write your code here */
|
||||
gpa = g;
|
||||
} // Overloaded Constructor
|
||||
|
||||
@ -29,6 +36,11 @@ public:
|
||||
|
||||
double getGpa() const { return gpa; }
|
||||
|
||||
// Overloaded operators
|
||||
bool operator==(const Student& other) { return name == other.name; }
|
||||
|
||||
// friend functions
|
||||
friend int key_to_index(const Student& key, int size);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,27 +1,26 @@
|
||||
/*
|
||||
CIS 22C
|
||||
Hashing - Linear Probe: insert, search, and delete
|
||||
Hash Tables ADT - Linear Probe
|
||||
Written By: Iurii Tatishchev
|
||||
Reviewed & Modified by: Iurii Tatishchev
|
||||
*/
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "HashTable.h"
|
||||
#include "Student.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void buildHash(HashTable &hash);
|
||||
void buildHash(HashTable<Student> &hash);
|
||||
|
||||
void searchManager(const HashTable &hash);
|
||||
void searchManager(const HashTable<Student> &hash);
|
||||
|
||||
void deleteManager(HashTable &hash);
|
||||
void deleteManager(HashTable<Student> &hash);
|
||||
|
||||
void insertManager(HashTable &hash);
|
||||
void insertManager(HashTable<Student> &hash);
|
||||
|
||||
int main() {
|
||||
HashTable hash;
|
||||
HashTable<Student> hash;
|
||||
|
||||
buildHash(hash);
|
||||
cout << "Load Factor: " << hash.getLoadFactor() << endl;
|
||||
@ -36,7 +35,7 @@ int main() {
|
||||
This function builds a hash table with data from an array
|
||||
It calls the insert() function that inserts the new data at the right location in the hash table.
|
||||
************************************************** */
|
||||
void buildHash(HashTable &hash) {
|
||||
void buildHash(HashTable<Student> &hash) {
|
||||
|
||||
Student list[] = {{"Tom", 2.5},
|
||||
{"Bob", 3.2},
|
||||
@ -54,7 +53,7 @@ void buildHash(HashTable &hash) {
|
||||
{"", 0}};
|
||||
|
||||
for (int i = 0; list[i].getName() != ""; i++) {
|
||||
hash.insert(list[i]);
|
||||
hash.insert(list[i], key_to_index);
|
||||
}
|
||||
|
||||
}
|
||||
@ -64,14 +63,15 @@ This function searches a hash table with user provided data.
|
||||
It calls the hash search function in a loop.
|
||||
To stop searching enter "#"
|
||||
************************************************** */
|
||||
void searchManager(const HashTable &hash) {
|
||||
void searchManager(const HashTable<Student> &hash) {
|
||||
cout << endl << "~*~ Test Search ~*~" << endl;
|
||||
cout << "Enter name [# to stop searching]:" << endl;
|
||||
string name;
|
||||
getline(cin, name);
|
||||
while (name != "#") {
|
||||
Student item;
|
||||
int nc = hash.search(item, name);
|
||||
item.setName(name);
|
||||
int nc = hash.search(item, item, key_to_index);
|
||||
if (nc != -1) {
|
||||
cout << item.getName() << " " << item.getGpa() << " (" << nc << " collisions!)" << endl;
|
||||
} else {
|
||||
@ -79,6 +79,7 @@ void searchManager(const HashTable &hash) {
|
||||
}
|
||||
getline(cin, name);
|
||||
}
|
||||
cout << "Load Factor: " << hash.getLoadFactor() << endl;
|
||||
}
|
||||
|
||||
/* **************************************************
|
||||
@ -86,21 +87,22 @@ This function deletes user provided data data from a hash table
|
||||
It calls the hash delete function in a loop.
|
||||
To stop deleting enter "#"
|
||||
************************************************** */
|
||||
void deleteManager(HashTable &hash) {
|
||||
void deleteManager(HashTable<Student> &hash) {
|
||||
cout << endl << "~*~ Test Delete ~*~" << endl;
|
||||
cout << "Enter name [# to stop deleting]:" << endl;
|
||||
string name;
|
||||
getline(cin, name);
|
||||
while (name != "#") {
|
||||
Student itemOut;
|
||||
if (hash.remove(itemOut, name)) {
|
||||
itemOut.setName(name);
|
||||
if (hash.remove(itemOut, itemOut, key_to_index)) {
|
||||
cout << itemOut.getName() << " " << itemOut.getGpa() << " - deleted!" << endl;
|
||||
} else {
|
||||
cout << name << " not found!" << endl;
|
||||
}
|
||||
cout << "Load Factor: " << hash.getLoadFactor() << endl;
|
||||
getline(cin, name);
|
||||
}
|
||||
cout << "Load Factor: " << hash.getLoadFactor() << endl;
|
||||
}
|
||||
|
||||
/* **************************************************
|
||||
@ -109,14 +111,15 @@ It rejects duplicates.
|
||||
It calls hash search and hash insert in a loop.
|
||||
To stop getting user input enter "#"
|
||||
************************************************** */
|
||||
void insertManager(HashTable &hash) {
|
||||
void insertManager(HashTable<Student> &hash) {
|
||||
cout << endl << "~*~ Test Insert - reject duplicates ~*~" << endl;
|
||||
cout << "Enter name [# to stop reading]:" << endl;
|
||||
string name;
|
||||
getline(cin, name);
|
||||
while (name != "#") {
|
||||
Student found;
|
||||
if (hash.search(found, name) != -1) {
|
||||
found.setName(name);
|
||||
if (hash.search(found, found, key_to_index) != -1) {
|
||||
cout << "Duplicate key: " << found.getName() << " - rejected!" << endl;
|
||||
} else {
|
||||
cout << "Enter gpa:" << endl;
|
||||
@ -124,11 +127,11 @@ void insertManager(HashTable &hash) {
|
||||
cin >> gpa;
|
||||
cin.ignore();
|
||||
Student newStudent(name, gpa);
|
||||
hash.insert(newStudent);
|
||||
cout << name << " - inserted (" << hash.search(found, name) << " collisions)" << endl;
|
||||
hash.insert(newStudent, key_to_index);
|
||||
cout << name << " - inserted (" << hash.search(found, newStudent, key_to_index) << " collisions)" << endl;
|
||||
}
|
||||
cout << "Load Factor: " << hash.getLoadFactor() << endl;
|
||||
cout << "Enter name [# to stop reading]:" << endl;
|
||||
getline(cin, name);
|
||||
}
|
||||
cout << "Load Factor: " << hash.getLoadFactor() << endl;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user