I have to write an ArrayDictionary.cpp file that follows the ArrayDictionary.h file listed below. The purpose of the .h file is an array-based implementation of the ADT dictionary that organizes its data items in sorted search-key order. Search keys in the dictionary are unique.
The code includes ArrayDictionary.h and ArrayDictionary.cpp. The ArrayDictionary.h file also includes other .h files. Please let me know if you need them to help me.
I'm having trouble with variables that cannot be identify in the ArrayDicionary.cpp file. The variables are items and entryCount that are having errors.
//ArrayDictionary.h
#pragma once
#ifndef _ARRAY_DICTIONARY
#define _ARRAY_DICTIONARY
#include "DictionaryInterface.h"
#include "Entry.h"
#include "NotFoundException.h"
#include "PrecondViolatedExcept.h"
template < class KeyType, class ValueType>
class ArrayDictionary : public DictionaryInterface < KeyType, ValueType>
{
private:
static const int DEFAULT_CAPACITY = 21; // Small capacity to test for
// a full dictionary
Entry<KeyType, ValueType>* entries; // Array of dictionary entries
int entryCount; // Maximum capacity of the dictionary
void destroyDictionary();
int findEntryIndex(int firstIndex, int lastIndex, const KeyType & searchKey) const;
int maxEntries;
public:
ArrayDictionary();
ArrayDictionary(int maxNumberOfEntries);
ArrayDictionary(const ArrayDictionary<KeyType, ValueType>&dictionary);
virtual ~ArrayDictionary();
bool isEmpty() const;
int getNumberOfEntries() const;
bool add(const KeyType& searchKey, const ValueType& newValue) throw (PrecondViolatedExcep);
bool remove(const KeyType& searchKey);
void clear();
ValueType getValue(const KeyType& searchKey) const throw (NotFoundException);
bool contains(const KeyType& searchKey) const;
/** Traverses the items in this dictionary in sorted search-key order
and calls a given client function once for each item. */
void traverse(void visit(ValueType&)) const;
}; // end ArrayDictionary
#include "ArrayDictionary.cpp"
#endif
#include <iostream>
#include "ArrayDictionary.h"
#include "PrecondViolatedExcept.h"
template < class KeyType, class ValueType>
void ArrayDictionary<KeyType, ValueType>::destroyDictionary()
{
delete[] items;
items = new Entry[maxEntries];
entryCount = 0;
}
template < class KeyType, class ValueType>
inline int findEntryIndex(int firstIndex, int lastIndex, const KeyType& searchKey)
{
int IndexMiddle = firstIndex + (lastIndex - firstIndex) / 2;
if (firstIndex > lastIndex)
return -1;
else if (searchKey == items[IndexMiddle].getKey())
return IndexMiddle;
else if (searchKey < items[IndexMiddle].getKey())
return findEntryIndex(firstIndex, IndexMiddle - 1, searchKey);
else
return findEntryIndex(IndexMiddle + 1, lastIndex, searchKey);
}
template < class KeyType, class ValueType>
inline ArrayDictionary<KeyType, ValueType>::ArrayDictionary() : entryCount(0), maxEntries(DEFAULT_CAPACITY)
{
items = new Entry[DEFAULT_CAPACITY];
}
template < class KeyType, class ValueType>
inline ArrayDictionary<KeyType,ValueType>::ArrayDictionary(int maxNumberOfEntries) :
entryCount(0), maxEntries(maxNumberOfEntries)
{
items = new Entry[maxNumberOfEntries];
}
template < class KeyType, class ValueType>
inline ArrayDictionary<KeyType,ValueType>::ArrayDictionary(const ArrayDictionary& dictionary) :
entryCount(dictionary.itemCount), maxEntries(dictionary.maxEntries)
{
items = new Entry[dictionary.maxEntries];
for (int index = 0; index < dictionary.entryCount; index++)
{
items[index] = dictionary.items[index];
}
}
template < class KeyType, class ValueType>
inline ArrayDictionary<KeyType, ValueType>::~ArrayDictionary()
{
destroyDictionary();
}
template < class KeyType, class ValueType>
inline bool isEmpty()
{
return (entryCount == 0);
}
template < class KeyType, class ValueType>
inline int getNumberOfItems()
{
return entryCount;
}
template < class KeyType, class ValueType>
inline void ArrayDictionary<KeyType, ValueType>:: clear()
{
destroyDictionary();
}
template < class KeyType, class ValueType>
inline bool ArrayDictionary<KeyType, ValueType>::add(const KeyType& searchKey, const ValueType& newValue) throw (PrecondViolatedExcep)
{
bool ableToInsert = (entryCount < maxEntries);
if (ableToInsert)
{
// Make room for new entry by shifting all entries at
// positions >= newPosition toward the end of the array
// (no shift if newPosition == itemCount + 1). Performing
// a binary search doesn’t help here, because we need to
// shift the entries while looking for the insertion location.
int index = entryCount;
// Short-circuit evaluation is important
while ((index > 0) && (searchKey < items[index - 1].getKey()))
{
items[index] = items[index - 1];
index--;
} // end while
if (searchKey != items[index - 1].getKey())
{
items[index] = Entry<KeyType, ValueType>(searchKey, newValue);
entryCount++;
}
else
{
auto message = "Attempt to add entry whose search key exits in dictionary.";
throw (PrecondViolatedExcep(message);
}
return ableToInsert;
} // end add
}
template < class KeyType, class ValueType>
inline bool ArrayDictionary<KeyType, ValueType>:: remove(const const KeyType& itemKey)
{
int currentIndex = findEntryIndex(0, itemCount - 1, itemKey);
bool deletable = !isEmpty() && (currentIndex >= 0);
if (deletable)
{
while (currentIndex < entryCount - 1)
{
items[currentIndex] = items[currentIndex + 1];
currentIndex++;
}
itemCount--;
}
return deletable;
}
template < class KeyType, class ValueType>
inline ValueType getValue(const KeyType& searchKey) throw(NotFoundException)
{
int currentIndex = findEntryIndex(0, itemCount - 1, searchKey);
if (currentIndex < 0)
throw NotFoundException("nnItemis not in the Dictionary!nn");
return items[currentIndex].getItem();
}
template < class KeyType, class ValueType>
inline bool contains(const KeyType& searchKey)
{
return (findEntryIndex(0, entryCount - 1, itemKey) >= 0)
}
template < class KeyType, class ValueType>
inline void traverse(void visit(ValueType&))
{
for (int itr = 0; itr < entryCount; itr++)
{
ValueType currentItem = items[itr].getItem();
visit(currentItem);
}
}
Related
Currently my class looks like this, by unit tests done, it works but my goal will be to implement as precise in question the lib Boost and especially the multi index container.
I tried to change the type of the items but it didn't work, like this:
typedef multi_index_container<items,indexed_by<sequenced<>,hashed_unique<identity<Item> >>> item_list;
I got a message: Invalid use of non-static data member '_items'. This kind of error I can understand it but i not specify it because it is the global implementation that worries me
If you find any other error apart from my precise question, I am also a taker.
template<typename Tkey, typename Tval>
class CacheWeb{
private:
unsigned int capacity;
std::list<std::pair<Tkey, Tval>> items;
std::unordered_map<key, typename std::list<std::pair<Tkey, Tval>>::iterator> lookup;
CacheWeb(const CacheWeb&) = delete;
CacheWeb& operator=(const CacheWeb&) = delete;
int capacityOut(){
if( capacity == 0 || lookup.size() < capacity ) {
return 0;
}
int cnt = 0;
while(lookup.size() > capacity) {
lookup.erase(items.back().first);
items.pop_back();
++cnt;
}
return cnt;
};
public:
CacheWeb(int icapacity) : capacity(icapacity){};
virtual ~CacheWeb() = default;
int size(){
return lookup.size();
};
bool empty(){
return lookup.empty();
};
void clear(){
lookup.clear();
items.clear();
};
bool contains(const Tkey& key){
return lookup.find(key) != lookup.end();
};
void remove(const Tkey& key){
auto it = lookup.find(key);
items.erase(it->second);
lookup.erase(it);
};
void put(const Tkey& key, const Tval& val){
auto it = lookup.find(key);
if( it != lookup.end() ) {
it->second->second = val;
items.splice(items.begin(), items, it->second);
return;
}
items.emplace_front(key, val);
lookup[key] = items.begin();
capacityOut();
};
std::list<std::pair<Tkey, Tval>>getItems(){
return items;
};
const VAL_T& get(const Tkey& key){
const auto it = lookup.find(key);
if( it == lookup.end() ) {
throw std::invalid_argument("Key does not exist");
}
items.splice(items.begin(), items, it->second);
return it->second->second;
};
};
}
Something like this can do:
Live Coliru Demo
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/key.hpp>
template<typename Tkey, typename Tval>
class CacheWeb{
private:
using value_type = std::pair<Tkey, Tval>;
unsigned int capacity;
boost::multi_index_container<
value_type,
boost::multi_index::indexed_by<
boost::multi_index::sequenced<>,
boost::multi_index::hashed_unique<boost::multi_index::key<&value_type::first>>
>
> container;
CacheWeb(const CacheWeb&) = delete;
CacheWeb& operator=(const CacheWeb&) = delete;
int capacityOut(){
if( capacity == 0 || container.size() < capacity ) {
return 0;
}
int cnt = 0;
while(container.size() > capacity) {
container.pop_back();
++cnt;
}
return cnt;
};
public:
CacheWeb(int icapacity) : capacity(icapacity){};
virtual ~CacheWeb() = default;
int size(){
return container.size();
};
bool empty(){
return container.empty();
};
void clear(){
container.clear();
};
bool contains(const Tkey& key){
const auto& lookup = container.template get<1>();
return lookup.find(key) != container.template get<1>().end();
};
void remove(const Tkey& key){
container.erase(key);
};
void put(const Tkey& key, const Tval& val){
auto& lookup = container.template get<1>();
auto it = lookup.find(key);
if( it != lookup.end() ) {
lookup.modify(it,[&](value_type& x){ x.second = val; });
}
else{
it=lookup.emplace(key, val).first;
}
container.relocate(container.begin(),container.template project<0>(it));
capacityOut();
};
std::list<std::pair<Tkey, Tval>>getItems(){
return {container.begin(), container.end()};
};
const Tval& get(const Tkey& key){
const auto& lookup = container.template get<1>();
const auto it = lookup.find(key);
if( it == lookup.end() ) {
throw std::invalid_argument("Key does not exist");
}
return it->second;
}
};
#include <iostream>
int main()
{
CacheWeb<int,int> c(10);
for(int i=0;i<11;++i)c.put(i,i);
for(const auto& x:c.getItems()){
std::cout<<"("<<x.first<<","<<x.second<<")";
}
std::cout<<"\n";
for(int i=1;i<11;++i){
std::cout<<i<<"->"<<c.get(i)<<" ";
}
std::cout<<"\n";
}
Output
(10,10)(9,9)(8,8)(7,7)(6,6)(5,5)(4,4)(3,3)(2,2)(1,1)
1->1 2->2 3->3 4->4 5->5 6->6 7->7 8->8 9->9 10->10
I'm very very new to vectors and templates. Can't seem to wrap my head around them just yet.
The code is as follows:
template <class T>
class m_vector
{
int m_iNextIndex;
int m_iMaxSize;
T* m_pArray;
public:
m_vector()
{
m_pArray = 0;
init();
}
m_vector(const m_vector<T>& other)
{
m_pArray = 0;
m_iNextIndex = 0;
m_iMaxSize = 0;
*this = other;
}
~m_vector()
{
if (m_pArray != 0)
delete [] m_pArray;
}
void init()
{
m_iMaxSize = VECT_INC_SIZE;
m_pArray = new T[m_iMaxSize];
m_iNextIndex = 0;
}
inline void push_back(const T& item)
{
if (m_iNextIndex >= m_iMaxSize)
{
resize(m_iNextIndex + VECT_INC_SIZE);
m_iNextIndex -= VECT_INC_SIZE;
}
m_pArray[m_iNextIndex] = item;
++m_iNextIndex;
}
void resize(int iNewSize)
{
if (iNewSize >= m_iMaxSize)
{
T* temp = new T[iNewSize];
for (int i = 0; i < m_iNextIndex; ++i)
{
temp[i] = m_pArray[i];
}
delete [] m_pArray;
m_pArray = temp;
m_iMaxSize = iNewSize;
}
m_iNextIndex = iNewSize;
}
};
The push_back is called with Vectors that are (x, y) and rectangles that are (x, y, width, height).
I thought that since the code had "m_pArray[m_iNextIndex] = item" that I could simply add a new function to check that the item is unique before adding it to the vector list. So I coded a routine as follows:
int inline exists(const &item)
{
for(int i = 0; i < m_iMaxSize; i++)
{
if(m_pArray[i] == item)
return 1;
}
return 0;
}
The compiler was non to happy. It reported the following error on the if statement:
“left operand must be a pointer or pointer to class member, or arithmetic”
I'm thinking that I probably need something like:
if (type == vector)
if( (m_pArray[i].x == item.x) ....)
else
if( (m_pArray[i].x == item.x) && (m_pArray[i].width == item.width) )
Am I on the right track?
If so, how do I check the type of item.
Thx, Bill.
The problem is that your Vector or Rectangle are missing a comparison operator e.g.
friend bool operator== (Vector const& lhs, Vector const& rhs){
return lhs.x == rhs.x && lhs.y == rhs.y;
}
But the rest of you code is not good and needs a rewrite. I've rewritten my code to old-old style:
NOTE: DON'T BLINDLY COPY THIS CODE. ITS JUST FOR REFERENCE. TEST BEFORE YOU USE
#define VECT_INC_SIZE 10
// replaced by iterator version
//template< class InputIt, class Size, class OutputIt>
//OutputIt copy_n(InputIt first, Size count, OutputIt result) {
// while (count-- > 0) {
// *result++ = *first++;
// }
// return result;
//}
template<class InputIt, class OutputIt>
OutputIt copy(InputIt first, InputIt last, OutputIt d_first) {
while (first != last) {
*d_first++ = *first++;
}
return d_first;
}
template<class T>
T exchange(T& obj, T new_value)
{
T old_value = obj;
obj = new_value;
return old_value;
}
template <class T>
class m_vector
{
private:
unsigned int size;
unsigned int capacity;
T* array;
public:
m_vector()
: size(0)
, capacity(VECT_INC_SIZE)
, array(new T[VECT_INC_SIZE])
{}
m_vector(m_vector<T> const& other)
: size(other.size)
, capacity(other.capacity)
, array(new T[other.capacity]) {
//copy_n(other.array, size, array);
copy(other.cbegin(), other.cend(), begin());
}
// rule of 3
m_vector& operator=(m_vector<T> const& other) {
if (&other != this) {
if (other.capacity != capacity){
delete [] exchange(array, new T[other.capacity]);
capacity = other.capacity;
}
size = other.size;
//copy_n(other.array, size, array);
copy(other.cbegin(), other.cend(), begin());
}
return *this;
}
~m_vector() {
if (array != 0) delete [] array;
}
void push_back(T const& item) {
if (size >= capacity) {
reserve(capacity + VECT_INC_SIZE);
}
array[size] = item;
++size;
}
void reserve(unsigned int newCapacity) {
if (size > capacity) {
T* const temp = new T[newCapacity];
//copy_n(array, size, temp);
copy(cbegin(), cend(), temp);
delete [] exchange(array, temp);
capacity = newCapacity;
}
}
bool exists(T const& item) const {
//for(unsigned int i = 0; i < size; ++i) {
// if(array[i] == item) return true;
//}
for(T const* it = cbegin(); it != cend(); ++it) {
if(*it == item) return true;
}
return false;
}
void erase(T const& item) {
T* it = begin();
T* const endIt = end();
while(it != endIt && *it != item) ++it;
if (it == endIt) return;
copy(it + 1, endIt, it);
--size;
}
// iterators
T* begin() { return array; }
T* end() { return array + size; }
T const* cbegin() const { return array; }
T const* cend() const { return array + size; }
};
class Vector {
private:
int x,y;
public:
Vector() : x(0), y(0) {}
Vector(int x, int y) : x(x), y(y) {}
friend bool operator== (Vector const& lhs, Vector const& rhs){
return lhs.x == rhs.x && lhs.y == rhs.y;
}
friend bool operator!= (Vector const& lhs, Vector const& rhs){
return !(lhs==rhs);
}
};
#include <cstdio>
void VectorInM_Vector(m_vector<Vector> const& vec, Vector const& item) {
if (vec.exists(item)) printf("Vector found in vector\n");
else printf("Vector not found in vector\n");
}
int main(){
m_vector<Vector> vec;
vec.push_back(Vector(1,1));
VectorInM_Vector(vec, Vector(1,1));
m_vector<Vector> vec2(vec);
vec.erase(Vector(1,1));
VectorInM_Vector(vec, Vector(1,1));
VectorInM_Vector(vec2, Vector(1,1));
vec2 = vec;
VectorInM_Vector(vec2, Vector(1,1));
}
on compiler explorer/godbolt
When I try to compile this code, I get these errors from the Visual Studio compiler:
Error C2447 '{': missing function header (old-style formal list?) Binary Sarch Tree 127
Error C2061 syntax error: identifier 'Node' Binary Sarch Tree 127
Error C2143 syntax error: missing ';' before '{' Binary Sarch Tree 127
Line 127 is the implementation of Tree::find
HEADER FILE
#ifndef TREE_H
#define TREE_H
#include <iostream>
#include <limits>
#include <string>
#include <exception>
using namespace std;
class TreeException : public exception {
public:
TreeException(string msg) noexcept;
TreeException(const TreeException &src) noexcept;
TreeException &operator= (const TreeException &src) noexcept;
virtual ~TreeException();
virtual const char* what() const noexcept;
string msg;
};
const unsigned long custom_hash(const string &key);
template <class K, class C>
class Tree {
struct Node {
Node(const unsigned long hash, const K &key,
const C &container, const bool isDupl = false,
const Node *const parent = NULL);
unsigned long hash;
K key;
C container;
Node *parent, *left, *right, *dupl;
bool isDupl;
};
public:
Tree();
Tree(const Tree &src);
~Tree();
void add(const K &key, const C &container);
void remove(const K &key);
C &get(const K &key);
C &operator[](const K &key);
const unsigned int size() const;
private:
Node *const find(const K &key) const;
void destruct(const Node *curr);
Node *m_root;
};
#endif
IMPLEMENTATION FILE
#include "Tree.h"
//TreeException
TreeException::TreeException(string msg) noexcept
: msg(msg)
{}
TreeException::TreeException(const TreeException &src) noexcept {
msg = src.msg;
}
TreeException &TreeException::operator= (const TreeException &src) noexcept {
msg = src.msg;
return *this;
}
TreeException::~TreeException() {}
const char* TreeException::what() const noexcept {
return msg.c_str();
}
//Common
const unsigned long custom_hash(const string &key) {
unsigned long ret = 0;
for (unsigned int i = 0; i < key.length(); i++)
ret += key[i];
for (unsigned int i = 0; i < key.length(); i++) {
ret *= key[key[i] % key.length()];
ret %= ULONG_MAX;
}
return ret;
}
//Tree::Node
template <class K, class C>
Tree<K, C>::Node::Node(const unsigned long hash, const K &key,
const C &container, const bool isDupl,
const Node *const parent)
: hash(hash), key(key),
container(container), parent((Node*)parent),
left(NULL), right(NULL),
dupl(NULL), isDupl(false)
{}
//Tree
template <class K, class C>
Tree<K, C>::Tree()
: m_root(NULL)
{}
template <class K, class C>
Tree<K, C>::Tree(const Tree &src) {
}
template <class K, class C>
Tree<K, C>::~Tree() {
if (m_root)
destruct(m_root);
}
template <class K, class C>
void Tree<K, C>::add(const K &key, const C &container) {
const unsigned long h = custom_hash(key);
if (!m_root)
m_root = new Node(h, key, container);
else {
Node *curr = m_root;
while (curr->hash != h) {
if (h < curr->hash) {
if (curr->left)
curr = curr->left;
else
break;
} else {
if (curr->right)
curr = curr->right;
else
break;
}
}
if (curr->hash == h) {
if (curr->key == key)
throw TreeException("Key \"" + key + "\" already exists in the tree");
while (curr->dupl) {
curr = curr->dupl;
if (curr->key == key)
throw TreeException("Key \"" + key + "\" already exists in the tree");
}
curr->dupl = new Node(h, key, container, true, curr);
} else if (h < curr->hash) {
curr->left = new Node(h, key, container, false, curr);
} else {
curr->right = new Node(h, key, container, false, curr);
}
}
}
template <class K, class C>
void Tree<K, C>::remove(const K &key) {
}
template <class K, class C>
C &Tree<K, C>::get(const K &key) {
return find(key)->container;
}
template <class K, class C>
C &Tree<K, C>::operator[](const K &key) {
try {
return get(key);
} catch (exception &e) {
add(key, C());
return get(key);
}
}
template <class K, class C>
const unsigned int Tree<K, C>::size() const {
}
template <class K, class C>
Tree<K, C>::Node *const Tree<K, C>::find(const K &key) const {
if (!m_root)
throw TreeException("Tree is empty");
const unsigned long h = custom_hash(key);
Node *curr = m_root;
while (curr->hash != h) {
if (h < curr->hash) {
if (curr->left)
curr = curr->left;
else
break;
}
else {
if (curr->right)
curr = curr->right;
else
break;
}
}
if (curr->>hash != h)
throw TreeException("Key \"" + key + "\" couldn't be found");
while (curr->key != key && curr->dupl)
curr = curr->dupl;
if (curr->key != key)
throw TreeException("Key \"" + key + "\" couldn't be found");
return curr;
}
template <class K, class C>
void Tree<K, C>::destruct(const Node *curr) {
if (curr->left)
destruct(curr->left);
if (curr->right)
destruct(curr->right);
if (curr->dupl)
destruct(curr->dupl);
delete curr;
}
What could the problem be?
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have this code and I am suppose to re implement it using a quadratic probing method, the algorithm I have is
i = (i + count) % CAPACITY;. I'm not sure how I am supposed to do this, so help would be nice. I'm thinking you would just change the hash function and the next_index function, I'm not too sure. Here is the code I need to re-implement. Header file on top template on bottom.
#ifndef TABLE1_H
#define TABLE1_H
#include <cstdlib> // Provides size_t
namespace main_savitch_12A
{
template <class RecordType>
class table
{
public:
// MEMBER CONSTANT -- See Appendix E if this fails to compile.
static const std::size_t CAPACITY = 811;
// CONSTRUCTOR
table( );
// MODIFICATION MEMBER FUNCTIONS
void insert(const RecordType& entry);
void remove(int key);
// CONSTANT MEMBER FUNCTIONS
bool is_present(int key) const;
void find(int key, bool& found, RecordType& result) const;
std::size_t size( ) const { return used; }
private:
// MEMBER CONSTANTS -- These are used in the key field of special records.
static const int NEVER_USED = -1;
static const int PREVIOUSLY_USED = -2;
// MEMBER VARIABLES
RecordType data[CAPACITY];
std::size_t used;
// HELPER FUNCTIONS
std::size_t hash(int key) const;
std::size_t next_index(std::size_t index) const;
void find_index(int key, bool& found, std::size_t& index) const;
bool never_used(std::size_t index) const;
bool is_vacant(std::size_t index) const;
};
}
#include "table1.template" // Include the implementation.
#endif
//End Of Header
#include <cassert> // Provides assert
#include <cstdlib> // Provides size_t
namespace main_savitch_12A
{
template <class RecordType>
const std::size_t table<RecordType>::CAPACITY;
template <class RecordType>
const int table<RecordType>::NEVER_USED;
template <class RecordType>
const int table<RecordType>::PREVIOUSLY_USED;
template <class RecordType>
table<RecordType>::table( )
{
std::size_t i;
used = 0;
for (i = 0; i < CAPACITY; ++i)
data[i].key = NEVER_USED; // Indicates a spot that's never been used.
}
template <class RecordType>
void table<RecordType>::insert(const RecordType& entry)
// Library facilities used: cassert
{
bool already_present; // True if entry.key is already in the table
std::size_t index; // data[index] is location for the new entry
assert(entry.key >= 0);
// Set index so that data[index] is the spot to place the new entry.
find_index(entry.key, already_present, index);
// If the key wasn't already there, then find the location for the new entry.
if (!already_present)
{
assert(size( ) < CAPACITY);
index = hash(entry.key);
while (!is_vacant(index))
index = next_index(index);
++used;
}
data[index] = entry;
}
template <class RecordType>
void table<RecordType>::remove(int key)
// Library facilities used: cassert
{
bool found; // True if key occurs somewhere in the table
std::size_t index; // Spot where data[index].key == key
assert(key >= 0);
find_index(key, found, index);
if (found)
{ // The key was found, so remove this record and reduce used by 1.
data[index].key = PREVIOUSLY_USED; // Indicates a spot that's no longer in use.
--used;
}
}
template <class RecordType>
bool table<RecordType>::is_present(int key) const
// Library facilities used: assert.h
{
bool found;
std::size_t index;
assert(key >= 0);
find_index(key, found, index);
return found;
}
template <class RecordType>
void table<RecordType>::find(int key, bool& found, RecordType& result) const
// Library facilities used: cassert.h
{
std::size_t index;
assert(key >= 0);
find_index(key, found, index);
if (found)
result = data[index];
}
template <class RecordType>
inline std::size_t table<RecordType>::hash(int key) const
{
return (key % CAPACITY);
}
template <class RecordType>
inline std::size_t table<RecordType>::next_index(std::size_t index) const
// Library facilities used: cstdlib
{
return ((index+1) % CAPACITY);
}
template <class RecordType>
void table<RecordType>::find_index(int key, bool& found, std::size_t& i) const
// Library facilities used: cstdlib
{
std::size_t count; // Number of entries that have been examined
count = 0;
i = hash(key);
while((count < CAPACITY) && (data[i].key != NEVER_USED) && (data[i].key != key))
{
++count;
i = next_index(i);
}
found = (data[i].key == key);
}
template <class RecordType>
inline bool table<RecordType>::never_used(std::size_t index) const
{
return (data[index].key == NEVER_USED);
}
template <class RecordType>
inline bool table<RecordType>::is_vacant(std::size_t index) const
{
return (data[index].key == NEVER_USED) || (data[index].key == PREVIOUSLY_USED);
}
}
With this code you are doing linear probing
index = hash(entry.key);
while (!is_vacant(index))
index = next_index(index);
template <class RecordType>
inline std::size_t table<RecordType>::next_index(std::size_t index) const
// Library facilities used: cstdlib
{
return ((index+1) % CAPACITY);
}
Say your map is nearly full and hash returns 23, then the next slots you are going to test will be 24, 25, 26, 27, etc.
All that is different about quadratic probing is the pattern of slots to test when a slot is full. Again suppose hash returns 23, then the next slot to test will be 23 + 1 = 24, the next will be 23 + 4 = 27, the next will be 23 + 9 = 32, the next will be 23 + 16 = 39. See the pattern? Each time you are testing 23 + n*n. That is quadratic probing. Of course all values should be mod CAPACITY, like you are doing now.
In other words you don't need to change the hash function, just the while loop inside insert.
I'm writing an implementation of Deque as a programming exercise and it's not going too well at all. I'm missing a few key function that are needed to make the test main program I was given function correctly.
Here is my code so far:
#include <vector>
#include <iostream>
#include <cassert>
using namespace std;
template <class T> class DequeIterator;
template <class T>
class Deque {
public:
typedef DequeIterator<T> iterator;
Deque(): vecOne(), vecTwo() { }
Deque(unsigned int size, T& initial): vecOne(size/2, initial), vecTwo(size-(size/2), initial) { }
Deque(Deque<T> & d): vecOne(d.vecOne), vecTwo(d.vecTwo) { }
T & operator[](unsigned int);
T & front();//
T & back();//
bool empty(){ return vecOne.empty() && vecTwo.empty(); }
iterator begin() { return iterator(this,0); }
iterator end() { return iterator(this, size ()); }
void erase(const iterator &);
void erase(const iterator &, const iterator &);
void insert(const iterator &, const T &);
int size() { return vecOne.size() + vecTwo.size(); }
void push_front(const T & value) { vecOne.push_back(value); }
void push_back(const T & value) {vecTwo.push_back(value); }
void pop_front();
void pop_back();
protected:
vector<T> vecOne;
vector<T> vecTwo;
};
template <class T>//
T & Deque<T>::front()//returns the first element in the deque
{
if (vecOne.empty())
return vecTwo.front();
else
return vecOne.back();
}
template <class T>//
T & Deque<T>::back()//returns the last element in the deque
{
if (vecOne.empty())
return vecTwo.back();
else
return vecOne.front();
}
template <class T>//
T & Deque<T>::operator[] (unsigned int index)
{
int n = vecOne.size();
if (index < n)
return vecOne [ (n-1) - index ];
else
return vecTwo [ index - n ];
}
template <class T>//
Deque<T>::iterator DequeIterator<T>::operator ++ (int)
{
Deque<T>::iterator clone(theDeque, index);
index++;
return clone;
}
template <class T>//
void Deque<T>::pop_front()
{
}
template <class T>//
void Deque<T>::pop_back()
{
}
template <class T>//
void Deque<T>::erase (const iterator & itr)
{
int index = itr.index;
int n = vecOne.size();
if (index < n)
vecOne.erase (vecOne.begin() + ((n-1) - index));
else
vecTwo.erase (vecTwo.begin() + (n - index));
}
template <class T>//
void Deque<T>::erase (const iterator &, const iterator &)
{
}
template <class T>//
void Deque<T>::insert(const iterator &, const T &)
{
}
template <class T>
class DequeIterator {
friend class Deque<T>;
typedef DequeIterator<T> iterator;
public:
DequeIterator(): theDeque(0), index(0) { }
DequeIterator(Deque<T> * d, int i): theDeque(d), index(i) { }
DequeIterator(const iterator & d): theDeque(d.theDeque), index(d.index) { }
T & operator*() { return (*theDeque)[index]; }
iterator & operator++(int) { ++index; return *this; }
iterator operator++();
iterator operator--(int) { --index; return *this; }
iterator & operator--();
bool operator==(const iterator & r) { return theDeque == r.theDeque && index == r.index; }
bool operator!=(const iterator & r) { return theDeque == r.theDeque && index != r.index; }
bool operator< (const iterator & r) { return theDeque == r.theDeque && index < r.index; }
T & operator[](unsigned int i) { return (*theDeque) [index + i]; }
iterator operator=(const iterator & r) { theDeque = r.theDeque; index = r.index; }
iterator operator+(int i) { return iterator(theDeque, index + i); }
iterator operator-(int i) { return iterator(theDeque, index - i); }
protected:
Deque<T> * theDeque;
int index;
};
main()
{
Deque<int> d;
d.push_back(10);
d.push_back(20);
assert(d.front() == 10);
assert(d.back() == 20);
d.push_front(1);
d.push_front(2);
d.push_front(3);
assert(d.front() == 3);
assert(d.back() == 20);
d.pop_back();
d.pop_back();
d.pop_back();
assert(d.front() == 3);
assert(d.back() == 2);
d.push_back(1);
d.push_back(0);
Deque<int>::iterator i;
int counter = 3;
for (i = d.begin(); i != d.end(); i++)
assert(*i == counter--);
for (counter = 0; counter < d.size(); counter++)
assert(d[counter] == d.size()-counter-1);
i = d.begin() + 3;
Deque<int>::iterator j(i), k;
k = j = i - 2;
assert(*k == 2);
for (i = d.begin(); not(i == d.end()); ++i)
cout << *i << " ";
cout << endl;
d.erase(d.begin()+3);
//d.erase(d.begin(), d.begin()+2);
assert(d.size() == 1);
assert(d[0] == 1);
Deque<int> c(d);
c.front() = 3;
assert(c.back() == 3);
c.push_front(1);
c.insert(c.begin(), 0);
c.insert(c.begin()+2, 2);
for (i = c.begin(); not(i == c.end()); ++i)
cout << *i << " ";
cout << endl;
for (counter = 0; counter < c.size(); counter++)
assert(c[counter] == counter);
cout << "SUCCESS\n";
}
I was wondering if someone could tell me my function from line 66 is returning:
expected constructor, destructor, or type conversion before 'DequeIterator'
Because I'm not sure what I'm doing wrong in it. Also, if someone would be kind enough to give me an example of the pop_front() function so that I can use it to create the pop_back() function as well, that would be great. Lastly, I have on of the erase functions completed but I am not sure how to go about creating the second one, which basically erases a value within the range of two iterators, it is referenced in line 176.
Any help would be greatly appreciated. Thank you in advance.
As for the error, you probably need a typename before Deque<T>::iterator on that line.
typename Deque<T>::iterator DequeIterator<T>::operator++(int)
I think it is a great programming exercise to implement deque. But a prerequisite is to implement vector and list. deque is one of the most complicated std::containers to implement. You should start with one of the simpler ones (vector and list).
Well, you get the error on line 65 because you return an object of a class that hasn't been defined. You only have the forward declaration (prototype) for class DequeIterator, not the implementation.
void pop_back() {
vecTwo.pop_back();
}
void pop_front() {
vecOne.pop_back();
}