ST Using Binary search (ordered array)
Associative Array Abstraction
Associate one value with each key.
Method Search() throws an exception if the key is not present.
Method put() overwrites old value with new value.
Smbol Table.h
#pragma once
using namespace std;
template <typename Key, typename Value>
class ST
{
Key *keys;
Value *vals;
int n;
int elements = 0;
int i = -1; // increment before insertion & decrement after deletion
bool isEmpty();
bool isFull();
public:
ST(int);
int size();
void put(Key, Value);
bool delPair(Key);
bool deleteMin();
bool deleteMax();
void max();
void min();
bool contain(Key);
Value get(Key);
int rank(Key);
void print();
Key getKey(int) ;
};
template <typename Key, typename Value>
int ST<Key, Value>::size()
{
return elements;
}
template <typename Key, typename Value>
Key ST<Key, Value>::getKey(int i)
{
return keys[i];
}
template <typename Key, typename Value>
bool ST<Key, Value>::isEmpty()
{
return elements == 0;
}
template <typename Key, typename Value>
bool ST<Key, Value>::isFull()
{
return elements == n;
}
template <typename Key, typename Value>
ST<Key, Value>::ST(int n)
{
this->n = n;
keys = new Key[n];
vals = new Value[n];
}
template <typename Key, typename Value>
void ST<Key, Value>::put(Key key, Value val)
{
if (elements == 0)
{
i++;
keys[i] = key;
vals[i] = val;
elements++;
return;
}
int j = rank(key); // gives the index where to insert the new key & value or location of the key that's already present
// if Key already in the table, jsut change its value
if (j <= i && keys[j] == key)
{
vals[j] = val;
}
else
{
// resizing array
if (isFull())
{
n = n * 2;
Key *temp1 = new Key[n];
Value *temp2 = new Value[n];
for (int k = 0; k <= i; k++)
{
temp1[k] = keys[k];
temp2[k] = vals[k];
}
keys = temp1;
vals = temp2;
}
// first insert at the end
i++;
keys[i] = key;
vals[i] = val;
// second swap kth element with ith(Last) element until k < i
for (int k = j; k < i; k++)
{
swap(keys[k], keys[i]);
swap(vals[k], vals[i]);
}
// -- slide logic --
// Key Ktemp = keys[j];
// Value Vtemp = vals[j];
// // Insert in the SORT order.
// for (int k = j; k < i; k++)
// {
// swap(Ktemp, keys[k + 1]);
// swap(Vtemp, vals[k + 1]);
// }
// i++;
// keys[i] = Ktemp;
// vals[i] = Vtemp;
// inserting new key and value at its right location.
// keys[j] = key;
// vals[j] = val;
elements++;
}
}
template <typename Key, typename Value>
bool ST<Key, Value>::delPair(Key key)
{
if (isEmpty())
return false;
if (keys[i] == key)
{
return deleteMax();
}
int delIndex = rank(key);
if (keys[delIndex] == key)
{
// shifting one step backward or use the insertion logic
for (int k = i; k > delIndex; k--)
{
swap(keys[delIndex], keys[k]);
swap(vals[delIndex], vals[k]);
}
i--;
elements--;
return true;
}
return false;
}
template <typename Key, typename Value>
bool ST<Key, Value>::deleteMin()
{
return delPair(keys[0]);
}
template <typename Key, typename Value>
bool ST<Key, Value>::deleteMax()
{
if (isEmpty())
{
cout << "Empty symbol table" << endl;
return false;
}
i--;
elements--;
return true;
}
template <typename Key, typename Value>
void ST<Key, Value>::max()
{
if (isEmpty())
cout << "Empty symbol table" << endl;
cout << keys[i] << ":" << vals[i];
}
template <typename Key, typename Value>
void ST<Key, Value>::min()
{
if (isEmpty())
cout << "Empty symbol table" << endl;
cout << keys[0] << ":" << vals[0];
}
template <typename Key, typename Value>
bool ST<Key, Value>::contain(Key key)
{
int k = rank(key);
return k <= i && keys[k] == key;
}
template <typename Key, typename Value>
Value ST<Key, Value>::get(Key key)
{
if (isEmpty())
throw runtime_error("Search operation on empty symbol table.");
int k = rank(key);
if (k <= i && keys[k] == key)
return vals[k];
else
throw invalid_argument("Key not found in the symbol table.");
}
template <typename Key, typename Value>
int ST<Key, Value>::rank(Key key)
{
int s = 0, e = i;
while (s <= e)
{
int mid = s + (e - s) / 2;
if (keys[mid] == key)
return mid;
else if (keys[mid] < key)
s = mid + 1;
else
e = mid - 1;
}
return s;
}
template <typename Key, typename Value>
void ST<Key, Value>::print()
{
for (int j = 0; j < elements; j++)
{
cout << keys[j] << " : " << vals[j] << endl;
}
}
main.cpp
#include <iostream>
#include "Symbol Table.h"
int main()
{
try
{
// ST<string, int> *st = new ST<string, int>(5);
// st->put("Banana", 0);
// st->put("Aapple", 1);
// st->put("Apple", 2);
// cout << (boolalpha) << st->delPair("Apple") << endl;
ST<char, int> *st = new ST<char, int>(5);
st->put('S', 0);
st->put('E', 1);
st->put('A', 2);
st->put('R', 3);
st->put('C', 4);
st->put('H', 5);
st->put('E', 6);
st->put('X', 7);
st->put('A', 8);
st->put('M', 9);
st->put('P', 10);
st->put('L', 11);
st->put('E', 12);
cout << (boolalpha) << st->delPair('X') << endl;
cout << (boolalpha) << st->contain('X') << endl;
st->deleteMin();
st->print();
cout << "Value At Key: " << st->get('A') << endl;
delete st;
}
catch (const runtime_error &e)
{
cerr << "Runtime error: " << e.what() << endl; // cerr is the standard error stream, typically used for error messages and diagnostics.
}
catch (const invalid_argument &e)
{
cerr << "Invalid argument: " << e.what() << endl;
}
catch (...)
{
cerr << "An unexpected error occurred." << endl;
}
}
Last updated
Was this helpful?