#include <iostream>
#include <string>
#include "HashTable.h"
using namespace std;
struct MyStruct {
string str;
int num;
bool operator ==( const MyStruct & r ) { return str == r.str; }
};
const int SIZE1 = 97;
int hash1( const MyStruct & obj );
int main( )
{
HashTable<MyStruct> ht1( hash1, SIZE1 );
MyStruct myobj;
myobj.str = "elephant";
myobj.num = 25;
ht1.insert( myobj );
MyStruct myobj2;
myobj2.str = "elephant";
ht1.retrieve( myobj2 );
cout << "retrieved from ht1: " << myobj2.num << " for num." << endl;
return 0;
}
int hash1( const MyStruct & obj )
{
int sum = 0;
for ( int i = 0; i < 3 && i < int( obj.str.length( ) ); i++ )
sum += obj.str[ i ];
return sum % SIZE1;
}
This is the code for my main function, I am getting a crap ton of errors, and cannot find anything wrong.
H:\CSC 375\Homework5\LinkedList.h|200|warning: no newline at end of file|
H:\CSC 375\Homework5\Array.h||In constructor `Array<DataType>::Array(int)':|
H:\CSC 375\Homework5\Array.h|46|error: expected primary-expression before "template"|
H:\CSC 375\Homework5\Array.h|46|error: expected `;' before "template"|
repeats for each use of template
H:\CSC 375\Homework5\HashTable.h|6|error: expected primary-expression before "template"|
H:\CSC 375\Homework5\HashTable.h|6|error: expected `;' before "template"|
repeats for each use of template
H:\CSC 375\Homework5\HashTable.h|82|warning: no newline at end of file|
H:\CSC 375\Homework5\main.cpp|17|error: expected primary-expression before "int"|
H:\CSC 375\Homework5\main.cpp|17|error: expected `;' before "int"|
H:\CSC 375\Homework5\main.cpp|38|error: a function-definition is not allowed here before '{' token|
H:\CSC 375\Homework5\main.cpp|38|error: expected `,' or `;' before '{' token|
H:\CSC 375\Homework5\main.cpp|44|warning: no newline at end of file|
H:\CSC 375\Homework5\main.cpp|43|error: expected `}' at end of input|
||=== Build finished: 35 errors, 3 warnings (0 minutes, 0 seconds) ===|
EDIT: Linked List, Array, and HashTable all compile and build fine without main.cpp, so it has to be something in that file.
Double EDIT: Code for the files (I put interface and implimentation in same file when using templates, too many problems linking a .h and .cpp)
// HashTable.h
#include "LinkedList.h"
#include "Array.h"
template <class DataType>
class HashTable
{
public:
HashTable( int (*hashf)(const DataType &), int s );
bool Insert( const DataType & newObject );
bool retrieve( DataType & retrieved );
bool Remove( DataType & removed );
bool update( DataType & updateObject );
void makeEmpty( );
private:
Array< LinkedList<DataType> > table;
int (*hashfunction)(const DataType &);
};
// HashTable.cpp
template <class DataType>
HashTable<DataType>::HashTable( int (*hashf)(const DataType &), int s )
: table( s )
{
hashfunc = hashf;
}
template <class DataType>
bool HashTable<DataType>::Insert( const DataType & newObject )
{
int location = hashfunc( newObject );
if ( location < 0 || location >= table.length( ) )
return false;
table[ location ].Insert( newObject );
return true;
}
template <class DataType>
bool HashTable<DataType>::retrieve( DataType & retrieved )
{
int location = hashfunc( retrieved );
if ( location < 0 || location >= table.length( ) )
return false;
if ( !table[ location ].retrieve( retrieved ) )
return false;
return true;
}
template <class DataType>
bool HashTable<DataType>::Remove( DataType & removed )
{
int location = hashfunc( removed );
if ( location < 0 || location >= table.length( ) )
return false;
if ( !table[ location ].Remove( removed ) )
return false;
return true;
}
template <class DataType>
bool HashTable<DataType>::update( DataType & updateObject )
{
int location = hashfunc( updateObject );
if ( location < 0 || location >= table.length( ) )
return false;
if ( !table[location].find( updateObject ) )
return false;
table[location].Replace( updateObject );
return true;
}
template <class DataType>
void HashTable<DataType>::makeEmpty( )
{
for ( int i = 0; i < table.length( ); i++ )
table[ i ].makeEmpty( );
}
....
// Array.h
#include <string>
using namespace std;
template <class DataType>
class Array
{
public:
Array( int Size );
Array( const Array<DataType> & ap );
~Array( );
Array<DataType> & operator =( const Array<DataType> & right );
inline DataType & operator [ ]( int index );
void changeSize( int newSize );
inline int length( ) const;
string err( ) const;
private:
DataType *elements;
int capacity;
DataType dud;
int errorCode;
inline void deepCopy( const Array<DataType> & original );
};
// Array.cpp
template <class DataType>
Array<DataType>::Array( int Size )
{
if ( Size < 1 ) {
capacity = 1;
errorCode = 1;
}
else {
capacity = Size;
errorCode = 0;
elements = new DataType [capacity];
}
template <class DataType>
Array<DataType>::Array( const Array<DataType> & ap )
{
deepCopy( ap );
}
template <class DataType>
Array<DataType>::~Array( )
{
delete [ ] elements;
}
template <class DataType>
Array<DataType> & Array<DataType>::operator =( const Array<DataType> & right )
{
if ( this == &right )
return *this;
delete [ ] elements;
deepCopy( right );
return *this;
}
template <class DataType>
inline DataType & Array<DataType>::operator [ ]( int index )
{
#ifdef DEBUG_ARRAY
if ( index < 0 || index >= capacity ) {
errorCode |= 2;
return dud;
}
#endif
return elements[ index ];
}
template <class DataType>
void Array<DataType>::changeSize( int newSize )
{
if ( newSize < 1 )
{
errorCode |= 4;
return;
}
DataType *newArray = new DataType [newSize];
int limit = (newSize > capacity)? capacity : newSize;
for ( int i = 0; i < limit; i++ )
newArray[ i ] = elements[ i ];
delete [ ] elements;
elements = newArray;
capacity = newSize;
}
template <class DataType>
inline int Array<DataType>::length( ) const
{
return capacity;
}
template <class DataType>
string Array<DataType>::err( ) const
{
if ( errorCode == 0 )
return "No error.\n";
string errorMessage = "";
if ( errorCode & 1 ) {
errorMessage += "Nonpositive size passed into constructor, so\n";
errorMessage += "the capacity was set to 1 by default.\n";
}
if ( errorCode & 2 )
errorMessage += "Index out of range.\n";
if ( errorCode & 4 ) {
errorMessage += "Nonpositive size passed into changeSize, so\n";
errorMessage += "the size of the array was not changed.\n";
}
return errorMessage;
}
template <class DataType>
inline void Array<DataType>::deepCopy( const Array<DataType> & original )
{
capacity = original.capacity;
errorCode = original.errorCode;
elements = new DataType [capacity];
for ( int i = 0; i < capacity; i++ )
elements[ i ] = original.elements[ i ];
}
Most of the code was provided by our textbook, I just need it to run, Please Help!
template <class DataType>
Array<DataType>::Array( int Size )
{
if ( Size < 1 ) {
capacity = 1;
errorCode = 1;
}
else {
capacity = Size;
errorCode = 0;
}//This is missing
elements = new DataType [capacity];
}
Also using namespaces in headers is a bad idea.
In the implementation of the Array( int Size ) constructor, the else case is missing it's closing brace }.
Related
I have structure called NodeID. When I create the unordered_set for this, I get the following compilation error
Error C2678 binary '<': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)
#include <iostream>
#include <unordered_set>
#include <map>
#include <set>
using namespace std;
struct NodeID
{
// Constructor
NodeID();
int mRgnID;
unsigned int mGID;
// Equal operator
bool operator == ( const NodeID& rhs ) const;
// Less than operator
bool operator < ( const NodeID& rhs ) const;
size_t operator()( const NodeID& n ) const noexcept
{
return n.mGID;
};
};
NodeID::NodeID()
{
mRgnID = -1;
mGID = 0;
}
//----------------------------------------------------------------------------------------
// Function : operator ==
// Purpose : Equal operator
bool NodeID::operator == ( const NodeID& rhs ) const
{
if (mRgnID != rhs.mRgnID)
return false;
if (mGID != rhs.mGID)
return false;
return true;
}
//----------------------------------------------------------------------------------------
// Function : operator <
// Purpose : Less than operator
bool NodeID::operator < ( const NodeID & rhs ) const
{
if (mRgnID < rhs.mRgnID)
return true;
else if (mRgnID > rhs.mRgnID)
return false;
else
{
if (mGID < rhs.mGID)
return true;
else if (mGID > rhs.mGID)
return false;
}
return false;
}
namespace std {
template<>
struct hash<NodeID>
{
std::size_t operator()( const NodeID& p ) const
{
return hash<int>()(p.mGID);
}
};
}
typedef std::unordered_set<NodeID> NodeSet;
int main()
{
NodeSet s;
NodeID n;
n.mGID = 2;
n.mRgnID = 0;
s.insert( n );
std::map<NodeSet, int> m;
m.insert( std::make_pair(s, 1) );
}
I have defined the less than operator in the NodeID structure
The answer here does not work for this pattern in C++17:
template <typename Processor>
void Collection::ProcessCollection(Processor & processor) const
{
for( int idx = -1 ; ++idx < m_LocalLimit ; )
{
if ( m_Data[ idx ] )
{
processor( m_Data[idx] );
}
}
const int overflowSize = OverflowSize();
for( int idx = -1 ; ++idx < overflowSize ; )
{
processor( (*m_Overflow)[ idx ] );
}
}
// How to avoid this repetition for non-const version?
template <typename Processor>
void Collection::ProcessCollection(Processor & processor)
{
for( int idx = -1 ; ++idx < m_LocalLimit ; )
{
if ( m_Data[ idx ] )
{
processor( m_Data[idx] );
}
}
const int overflowSize = OverflowSize();
for( int idx = -1 ; ++idx < overflowSize ; )
{
processor( (*m_Overflow)[ idx ] );
}
}
Due to the argument passed to the lambda Processor being const and not matching its signature.
You can factor out the function as a static template one and use it inside both. We can use the template to generate both of these functions:
struct Collection {
// ...
template<typename Processor>
void ProcessCollection(Processor& processor) {
ProcessCollectionImpl(*this, processor);
}
template<typename Processor>
void ProcessCollection(Processor& processor) const {
ProcessCollectionImpl(*this, processor);
}
template<typename T, typename Processor>
static void ProcessCollectionImpl(T& self, Processor& processor) {
for( int idx = -1 ; ++idx < self.m_LocalLimit ; )
{
if ( self.m_Data[ idx ] )
{
processor( self.m_Data[idx] );
}
}
const int overflowSize = self.OverflowSize();
for( int idx = -1 ; ++idx < overflowSize ; )
{
processor( (*self.m_Overflow)[ idx ] );
}
}
};
The T& will deduce Collection& or Collection const& depending on the constness of *this
I posted earlier today and was able to work out a lot of my errors. However, I still have one error that I cannot figure out for the life of me. I'm basically just trying to insert a Symbol object into a HashTable and I'm constantly getting this message back:
In file included from /opt/local/include/gcc47/c++/bits/basic_string.h:3032:0,
from /opt/local/include/gcc47/c++/string:54,
from /opt/local/include/gcc47/c++/bits/locale_classes.h:42,
from /opt/local/include/gcc47/c++/bits/ios_base.h:43,
from /opt/local/include/gcc47/c++/ios:43,
from /opt/local/include/gcc47/c++/ostream:40,
from /opt/local/include/gcc47/c++/iostream:40,
from Driver.cpp:1:
/opt/local/include/gcc47/c++/bits/functional_hash.h: In instantiation of 'struct std::hash<Symbol>':
SeparateChaining.h:143:33: required from 'size_t HashTable<HashedObj>::myhash(const HashedObj&) const [with HashedObj = Symbol; size_t = long unsigned int]'
SeparateChaining.h:56:51: required from 'bool HashTable<HashedObj>::insert(HashedObj&) [with HashedObj = Symbol]'
Driver.cpp:135:26: required from here
/opt/local/include/gcc47/c++/bits/functional_hash.h:60:7: error: static assertion failed: std::hash is not specialized for this type
More specifically though.... The error:
error: static assertion failed: std::hash is not specialized for this type
Here is my Driver.cpp file:
#include <iostream>
#include <iomanip>
#include <cassert>
#include <fstream>
#include <string>
#include <vector>
#include <time.h>
#include <unistd.h>
#include <map>
#include <cstdlib>
#include <cmath>
#include "SeparateChaining.h"
using namespace std;
int TABLE_SIZE; //I know it's a global, but it allows the Table Size to be taken in within main() and used in hash()
size_t hash(const string & key);
class Symbol
{
private:
int key;
int type;
string data;
public:
const string & getData() const
{
return data;
}
int getType()
{
return type;
}
int getKey()
{
return labs(key);
}
void setType(int Type)
{
type = Type;
}
void setData(string Data)
{
data = Data;
}
void setKey(int Key)
{
key = Key;
}
bool operator== (const Symbol & rhs) const
{
return getData() == rhs.getData();
}
bool operator!= (const Symbol & rhs) const
{
return !(*this == rhs);
}
};
int main()
{
HashTable<Symbol> hashtable(TABLE_SIZE);
Symbol temp;
vector<Symbol> symbols;
string s;
int t;
int hash_key_array[TABLE_SIZE]; //array to hold hash key values
ifstream file;
file.open("symbols.txt");
if(!file)
{
cout << "System failed to open file.";
}
else
{
cout << "File successfully opened" << endl;
}
//for loop to read in the string name and the integer that follows the string name from symbols.txt
while(file >> s)
{
temp.setData(s);
file >> t;
temp.setType(t);
symbols.push_back(temp);
}
for(int i = 0; i < symbols.size(); i++)
{
cout << symbols[i].getData() << "\n";
cout << symbols[i].getType() << "\n";
}
cout << "What would you like the table size to be?" << endl;
cout << "Note: If the table size is greater than the number of objects" <<
" in the symbols.txt file, it will inevitably throw a segmentation fault" << endl;
cin >> TABLE_SIZE;
for(int j = 0; j < TABLE_SIZE; j++)
{
temp.setData(symbols[j].getData());
cout << temp.getData() << endl;
temp.setType(symbols[j].getType());
cout << temp.getType() << endl;
temp.setKey(::hash(symbols[j].getData()));
cout << "The key is: " << temp.getKey() << endl;
cout << endl;
hash_key_array[j] = temp.getKey();
for (int i = 0; i < TABLE_SIZE; i++)
{
if (i != j)
{
if (hash_key_array[i] == hash_key_array[j])
{
cout << endl;
cout << "Collision occurred at " << hash_key_array[i] << endl;
//rehash();
//cout << "The new key is: " << temp.getKey() << endl;
break;
}
}
}
hashtable.insert(temp);
}
}
size_t hash(const string & key)
{
size_t hashVal = 0;
for(char ch : key)
{
hashVal = 37 * hashVal + ch;
}
return labs(hashVal);
}
And my Header File.... SeperateChaining.h:
#ifndef SEPARATE_CHAINING_H
#define SEPARATE_CHAINING_H
#include <vector>
#include <list>
#include <string>
#include <algorithm>
#include <functional>
//#include "Hash.h"
using namespace std;
// SeparateChaining Hash table class
//
// CONSTRUCTION: an approximate initial size or default of 101
//
// ******************PUBLIC OPERATIONS*********************
// bool insert( x ) --> Insert x
// bool remove( x ) --> Remove x
// bool contains( x ) --> Return true if x is present
// void makeEmpty( ) --> Remove all items
int nextPrime( int n );
bool isPrime( int n );
template <typename HashedObj>
class HashTable
{
public:
//Uses the whatever value table_size has
//Otherwise, it will make a hash table of size 101
explicit HashTable( int TABLE_SIZE )
{
currentSize = 0;
theLists.resize(TABLE_SIZE);
}
bool contains( const HashedObj & x ) const
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[ myhash( x ) ];
//returns whatever you wanted to search for in the table provided it is there
return find( begin( whichList ), end( whichList ), x ) != end( whichList );
}
void makeEmpty( )
{
for( auto & thisList : theLists )
thisList.clear( );
}
bool insert(HashedObj & temp )
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[myhash( temp )];
//goes through the beginning and end of the list, and if it
//doesn't get to the end, then it found the object you wanted to insert in the hash table already
//prevents duplicate insertions
if( find( begin( whichList ), end( whichList ), temp ) != end( whichList) )
return false;
//otherwise, it has gotten to the end of the list without finding a duplicate
//and puts what you want to insert in the list
whichList.push_back( temp );
// Rehash; see Section 5.5
if( ++currentSize > theLists.size( ) )
rehash( );
return true;
}
bool insert(const HashedObj && x )
{
auto & whichList = theLists[ myhash( x ) ];
if( find( begin( whichList ), end( whichList ), x ) != end( whichList ) )
return false;
whichList.push_back( std::move( x ) );
// Rehash; see Section 5.5
if( ++currentSize > theLists.size( ) )
rehash( );
return true;
}
bool remove( const HashedObj & x )
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[ myhash( x ) ];
//trying to find x within the list
//the iterator points to the slot in the list that contains x
auto itr = find( begin( whichList ), end( whichList ), x );
//if it gets to the end of the list without finding what you want to remove, then it returns false
if( itr == end( whichList ) )
{
return false;
}
//if it finds x, it removes it from the list
whichList.erase( itr );
--currentSize;
return true;
}
/*
void printTable()
{
for(int i=0; i < symbols.size(); i++)
{
cout << "The hash table contains: " << symbols[i] << endl;
}
}
*/
private:
vector<list<HashedObj>> theLists; // The array of Lists
int currentSize;
void rehash( )
{
vector<list<HashedObj>> oldLists = theLists;
// Creates new double-sized, empty table
theLists.resize( nextPrime( 2 * theLists.size( ) ) );
for( auto & thisList : theLists )
thisList.clear( );
// Copies the old table into the new table
currentSize = 0;
for( auto & thisList : oldLists )
for( auto & x : thisList )
insert( std::move( x ) );
}
size_t myhash( const HashedObj & x ) const
{
static hash<HashedObj> hf;
return hf( x ) % theLists.size( );
}
};
int nextPrime( int n )
{
if( n % 2 == 0 )
{
++n;
}
for( ; !isPrime( n ); n += 2 )
{
}
return n;
}
bool isPrime( int n )
{
if( n == 2 || n == 3 )
return true;
if( n == 1 || n % 2 == 0 )
return false;
for( int i = 3; i * i <= n; i += 2 )
if( n % i == 0 )
return false;
return true;
}
#endif
I would really appreciate you guys helping me out!
You are doing this:
static hash<HashedObj> hf;
but you have not provided a hash template, or have not specialized std::hash for HashedObj.
You should avoid using namespace std;. Amongst other things, it is difficult to figure out which hash you want to get.
I'm designing a simple program that takes an object of the Symbol class which I have defined and inserts into a HashTable. I've been given the HashTable.h file which came from our textbook and as you'll see, it is designed to be able to handle any object.
I'm trying to insert my object via:
hashtable.insert(&temp) //where temp is the object
However, I'm getting these errors:
Driver.cpp: In function 'int main()':
Driver.cpp:127:27: error: no matching function for call to 'HashTable<Symbol>::insert(Symbol*)'
Driver.cpp:127:27: note: candidates are:
In file included from Driver.cpp:12:0:
SeperateChaining.h:50:10: note: bool HashTable<HashedObj>::insert(HashedObj&) [with HashedObj = Symbol]
SeperateChaining.h:50:10: note: no known conversion for argument 1 from 'Symbol*' to 'Symbol&'
SeperateChaining.h:72:10: note: bool HashTable<HashedObj>::insert(HashedObj&&) [with HashedObj = Symbol]
SeperateChaining.h:72:10: note: no known conversion for argument 1 from 'Symbol*' to 'Symbol&&'
Would you guys mind taking a look?
EDIT: When I try to insert by value as many of you suggested, I get back a ton of garbage but parsed out for errors there are two:
opt/local/include/gcc47/c++/bits/stl_algo.h:135:7: error: no match for 'operator==' in '__first.std::_List_iterator<_Tp>::operator*<Symbol>() == __val'
and
opt/local/include/gcc47/c++/bits/stl_algo.h:135:7: error: no match for 'operator==' in '__first.std::_List_iterator<_Tp>::operator*<Symbol>() == __val' –
Here's my driver file and hash table.h file:
Driver.cpp:
#include <iostream>
#include <iomanip>
#include <cassert>
#include <fstream>
#include <string>
#include <vector>
#include <time.h>
#include <unistd.h>
#include <map>
#include <cstdlib>
#include <cmath>
#include "SeperateChaining.h"
//#include "hash_chn.h"
using namespace std;
int TABLE_SIZE; //I know it's a global, but it allows the Table Size to be taken in within main() and used in hash()
size_t hash(const string & key);
class Symbol
{
private:
int key;
int type;
string data;
public:
const string & getData() const
{
return data;
}
int getType()
{
return type;
}
int getKey()
{
return labs(key);
}
void setType(int Type)
{
type = Type;
}
void setData(string Data)
{
data = Data;
}
void setKey(int Key)
{
key = Key;
}
};
int main()
{
HashTable<Symbol> hashtable(TABLE_SIZE);
Symbol temp;
vector<Symbol> symbols;
string s;
int t;
int hash_key_array[TABLE_SIZE]; //array to hold hash key values
ifstream file;
file.open("symbols.txt");
if(!file)
{
cout << "System failed to open file.";
}
else
{
cout << "File successfully opened" << endl;
}
//for loop to read in the string name and the integer that follows the string name from symbols.txt
while(file >> s)
{
temp.setData(s);
file >> t;
temp.setType(t);
symbols.push_back(temp);
}
for(int i = 0; i < symbols.size(); i++)
{
cout << symbols[i].getData() << "\n";
cout << symbols[i].getType() << "\n";
}
cout << "What would you like the table size to be?" << endl;
cout << "Note: If the table size is greater than the number of objects" <<
" in the symbols.txt file, it will inevitably throw a segmentation fault" << endl;
cin >> TABLE_SIZE;
for(int j = 0; j < TABLE_SIZE; j++)
{
temp.setData(symbols[j].getData());
cout << temp.getData() << endl;
temp.setType(symbols[j].getType());
cout << temp.getType() << endl;
temp.setKey(::hash(symbols[j].getData()));
cout << "The key is: " << temp.getKey() << endl;
cout << endl;
hash_key_array[j] = temp.getKey();
for (int i = 0; i < TABLE_SIZE; i++)
{
if (i != j)
{
if (hash_key_array[i] == hash_key_array[j])
{
cout << endl;
cout << "Collision occurred at " << hash_key_array[i] << endl;
//rehash();
//cout << "The new key is: " << temp.getKey() << endl;
break;
}
}
}
hashtable.insert(&temp); //problem is here
}
}
size_t hash(const string & key)
{
size_t hashVal = 0;
for(char ch : key)
{
hashVal = 37 * hashVal + ch;
}
return labs(hashVal);
}
SeperateChaining.h:
#ifndef SEPARATE_CHAINING_H
#define SEPARATE_CHAINING_H
#include <vector>
#include <list>
#include <string>
#include <algorithm>
#include <functional>
//#include "Hash.h"
using namespace std;
// SeparateChaining Hash table class
//
// CONSTRUCTION: an approximate initial size or default of 101
//
// ******************PUBLIC OPERATIONS*********************
// bool insert( x ) --> Insert x
// bool remove( x ) --> Remove x
// bool contains( x ) --> Return true if x is present
// void makeEmpty( ) --> Remove all items
template <typename HashedObj>
class HashTable
{
public:
//Uses the whatever value table_size has
//Otherwise, it will make a hash table of size 101
explicit HashTable( int TABLE_SIZE )
{
currentSize = 0;
theLists.resize(TABLE_SIZE);
}
bool contains( const HashedObj & x ) const
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[ myhash( x ) ];
//returns whatever you wanted to search for in the table provided it is there
return find( begin( whichList ), end( whichList ), x ) != end( whichList );
}
void makeEmpty( )
{
for( auto & thisList : theLists )
thisList.clear( );
}
bool insert(HashedObj & temp )
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[myhash( temp )];
//goes through the beginning and end of the list, and if it
//doesn't get to the end, then it found the object you wanted to insert in the hash table already
//prevents duplicate insertions
if( find( begin( whichList ), end( whichList ), temp ) != end( whichList) )
return false;
//otherwise, it has gotten to the end of the list without finding a duplicate
//and puts what you want to insert in the list
whichList.push_back( temp );
// Rehash; see Section 5.5
if( ++currentSize > theLists.size( ) )
rehash( );
return true;
}
bool insert( HashedObj && x )
{
auto & whichList = theLists[ myhash( x ) ];
if( find( begin( whichList ), end( whichList ), x ) != end( whichList ) )
return false;
whichList.push_back( std::move( x ) );
// Rehash; see Section 5.5
if( ++currentSize > theLists.size( ) )
rehash( );
return true;
}
bool remove( const HashedObj & x )
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[ myhash( x ) ];
//trying to find x within the list
//the iterator points to the slot in the list that contains x
auto itr = find( begin( whichList ), end( whichList ), x );
//if it gets to the end of the list without finding what you want to remove, then it returns false
if( itr == end( whichList ) )
{
return false;
}
//if it finds x, it removes it from the list
whichList.erase( itr );
--currentSize;
return true;
}
/*
void printTable()
{
for(int i=0; i < symbols.size(); i++)
{
cout << "The hash table contains: " << symbols[i] << endl;
}
}
*/
private:
vector<list<HashedObj>> theLists; // The array of Lists
int currentSize;
void rehash( )
{
vector<list<HashedObj>> oldLists = theLists;
// Creates new double-sized, empty table
theLists.resize( nextPrime( 2 * theLists.size( ) ) );
for( auto & thisList : theLists )
thisList.clear( );
// Copies the old table into the new table
currentSize = 0;
for( auto & thisList : oldLists )
for( auto & x : thisList )
insert( std::move( x ) );
}
size_t myhash( const HashedObj & x ) const
{
static hash<HashedObj> hf;
return hf( x ) % theLists.size( );
}
};
#endif
hashtable.insert(&temp)
You have to insert by value, not by pointer. Remove the & operator.
hashtable.insert(&temp);
^
You are trying to insert an address of temp. This is what this error says:
note: bool HashTable::insert(HashedObj&) [with HashedObj =
Symbol] note: no known conversion for argument 1 from 'Symbol*' to
'Symbol&'
There is a version of insert that takes a reference as its argument. So instead of pointer insert the object by value:
hashtable.insert(temp);
Look at the errors you are getting:
SeperateChaining.h:50:10: note: bool HashTable<HashedObj>::insert(HashedObj&) [with HashedObj = Symbol]
SeperateChaining.h:50:10: note: no known conversion for argument 1 from 'Symbol*' to 'Symbol&'
SeperateChaining.h:72:10: note: bool HashTable<HashedObj>::insert(HashedObj&&) [with HashedObj = Symbol]
SeperateChaining.h:72:10: note: no known conversion for argument 1 from 'Symbol*' to 'Symbol&&'
This is telling you that you are calling insert with a Symbol* and the function insert takes either a Symbol& or a Symbol&&.
So, let's look at the code where you call insert:
hashtable.insert(&temp); //problem is here
Sure enough, you are using & which is the address-of operator which will take the address of temp, which is of type Symbol, returning a pointer to it (which is, of course, of type Symbol*). So you're calling the function with Symbol*, which is not what the functions expect.
Sidenote: your implementation has a few other issues that you will need to sort through. Ask yourself what is temp and what does the HashTable class do with the l- and r-value references to Symbol that it accepts?
i have to basically edit a quadratic probing file to work as a hash_map library but i'm having trouble overloading the subscript operator so i can modify that specefic index.
the code i have so far is:
template <typename HashedObj, typename storedObj >
class HashTable
{
public:
int& operator [] (const int nIndex)
{
return array[nIndex];//THIS IS WHATS WRONG
}
//create hashtable with siz of 101
explicit HashTable(int size = 101) : array( nextPrime( size ) )
{ makeEmpty( ); }
//return true if current index is active
bool contains( const HashedObj & x ) const
{
return isActive( findPos( x ) );
}
//initiallize index as empty
void makeEmpty( )
{
currentSize = 0;
for( int i = 0; i < array.size( ); i++ )
array[ i ].info = EMPTY;
}
//insert object into hash index and mark index as active
bool insert( const HashedObj & x )
{
// Insert x as active
int currentPos = findPos( x );
if( isActive( currentPos ) )
return false;
array[ currentPos ] = HashEntry( x, ACTIVE );
if( ++currentSize > array.size( ) / 2 )
rehash( );
return true;
}
//search for obj and mark index as deleted
bool remove( const HashedObj & x )
{
int currentPos = findPos( x );
if( !isActive( currentPos ) )
return false;
array[ currentPos ].info = DELETED;
return true;
}
//declare three different entry types
enum EntryType { ACTIVE, EMPTY, DELETED };
private:
//each hash index stores the following
struct HashEntry
{
//THIS WILL BE STRINGS OR INTS
HashedObj element;
//THIS WILL BE VECTOR STRINGS
storedObj ilement;
//index status is stored
EntryType info;
//each entry is made of hashed obj and stored obj and the status is empty
HashEntry( const HashedObj & e = HashedObj( ), const storedObj & f = storedObj( ),EntryType i = EMPTY )
: element( e ), ilement( f ),info( i ) { }
};
//create an array of hashentries
vector<HashEntry> array;
//currentsize of the hash table is stored here
int currentSize;
bool isActive( int currentPos ) const
{ return array[ currentPos ].info == ACTIVE; }
int findPos( const HashedObj & x ) const
{
int offset = 1;
int currentPos = myhash( x );
while( array[ currentPos ].info != EMPTY &&
array[ currentPos ].element != x )
{
currentPos += offset; // Compute ith probe
offset += 2;
if( currentPos >= array.size( ) )
currentPos -= array.size( );
}
return currentPos;
}
void rehash( )
{
vector<HashEntry> oldArray = array;
// Create new double-sized, empty table
array.resize( nextPrime( 2 * oldArray.size( ) ) );
for( int j = 0; j < array.size( ); j++ )
array[ j ].info = EMPTY;
// Copy table over
currentSize = 0;
for( int i = 0; i < oldArray.size( ); i++ )
if( oldArray[ i ].info == ACTIVE )
insert( oldArray[ i ].element );
}
int myhash( const HashedObj & x ) const
{
int hashVal = hashing( x );
hashVal %= array.size( );
if( hashVal < 0 )
hashVal += array.size( );
return hashVal;
}
};
int hashing( const string & key );
int hashing( int key );
the point is for main code to be able to do something like:
wordsByLength[words[i].length()] = words[i];
where words[i] will be a vector. i'm also assuming that i will need to modify the = operator later on but i'm not so sure
Think about what your subscript operator shall return. Is it int&? The simplest choice would be HashEntry:
template <typename HashedObj, typename storedObj >
class HashTable
{
public:
HashEntry& operator [] (int nIndex) // read/write version
{
return array[nIndex];
}
const HashEntry& operator [] (int nIndex) const // read only version
{
return array[nIndex];//THIS IS WHATS WRONG
}
...
};
But it is private. So either make it public - but this breaks somehow your encapsulation.
Because your are inserting HashedObj - then probably this is your desired return type:
template <typename HashedObj, typename storedObj >
class HashTable
{
public:
HashedObj& operator [] (int nIndex) // read/write version
{
return array[nIndex].element;
}
const HashedObj& operator [] (int nIndex) const // read only version
{
return array[nIndex].element;
}
...
};