Initial commit
This commit is contained in:
62
P1/Calculator.cpp
Normal file
62
P1/Calculator.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "Calculator.h"
|
||||
#include "VariableNode.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
Calculator::Calculator(int cap)
|
||||
{
|
||||
this->data = new VariableLinkedList(cap);
|
||||
}
|
||||
|
||||
Calculator::~Calculator()
|
||||
{
|
||||
delete this->data;
|
||||
}
|
||||
|
||||
/// @brief Define a new variable
|
||||
/// @param name The name of the new variable
|
||||
/// @param value The initial value to store in the variable
|
||||
/// @return True if the variable was added, false otherwise
|
||||
bool Calculator::define(string name, double value)
|
||||
{
|
||||
return this->data->insert(name, value);
|
||||
}
|
||||
|
||||
/// @brief Perform an operation on two variables, and store the result in a thrid
|
||||
/// @param v1 The first variable to perform the operation on
|
||||
/// @param v2 The second variable to perform the opetation on
|
||||
/// @param v3 The variable to store the output result in
|
||||
/// @param operation A lambda function to apply on the two variables
|
||||
/// @return True if successful, false otherwise
|
||||
bool Calculator::performOperation(string v1, string v2, string out, function<double(double, double)> operation)
|
||||
{
|
||||
VariableNode *vn1 = this->data->search(v1);
|
||||
VariableNode *vn2 = this->data->search(v2);
|
||||
VariableNode *output = this->data->search(out);
|
||||
|
||||
// If a single one of the variables is not found, we cannot continue.
|
||||
if (vn1 == nullptr || vn2 == nullptr || output == nullptr)
|
||||
return false;
|
||||
|
||||
output->setValue(operation(vn1->getValue(), vn2->getValue()));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Remove the given variable from storage
|
||||
/// @param name The name of the variable to remove
|
||||
/// @return True if the variable was successfully removed, false otherwise
|
||||
bool Calculator::remove(string name)
|
||||
{
|
||||
return this->data->remove(name);
|
||||
}
|
||||
|
||||
/// @brief Print out the value of the given variable
|
||||
/// @param name The name of the variable to print out
|
||||
void Calculator::print(string name)
|
||||
{
|
||||
VariableNode *temp = this->data->search(name);
|
||||
if (temp == nullptr)
|
||||
cout << "variable " << name << " not found" << endl;
|
||||
else
|
||||
cout << temp->getValue() << endl;
|
||||
}
|
||||
22
P1/Calculator.h
Normal file
22
P1/Calculator.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef CALCULATOR_H
|
||||
#define CALCULATOR_H
|
||||
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include "VariableNode.h"
|
||||
#include "VariableLinkedList.h"
|
||||
|
||||
class Calculator
|
||||
{
|
||||
public:
|
||||
bool define(std::string name, double value);
|
||||
bool performOperation(std::string v1, std::string v2, std::string output, std::function<double(double, double)> operation);
|
||||
bool remove(std::string name);
|
||||
void print(std::string name);
|
||||
Calculator(int cap);
|
||||
~Calculator();
|
||||
|
||||
private:
|
||||
VariableLinkedList *data;
|
||||
};
|
||||
#endif
|
||||
2
P1/Makefile
Normal file
2
P1/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
all: test.cpp Calculator.cpp VariableNode.cpp VariableLinkedList.cpp
|
||||
g++ -std=c++11 test.cpp Calculator.cpp VariableNode.cpp VariableLinkedList.cpp
|
||||
88
P1/VariableLinkedList.cpp
Normal file
88
P1/VariableLinkedList.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "VariableLinkedList.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
VariableLinkedList::VariableLinkedList(int cap)
|
||||
{
|
||||
this->maxCount = cap;
|
||||
this->count = 0;
|
||||
this->head = nullptr;
|
||||
}
|
||||
|
||||
VariableLinkedList::~VariableLinkedList()
|
||||
{
|
||||
if (head != nullptr)
|
||||
head->DestroyAll();
|
||||
}
|
||||
|
||||
/// @brief Insert a variable into the head of the linked list
|
||||
/// @param name The name of the variable to insert
|
||||
/// @param value The double value to initialize the variable with
|
||||
/// @return True if the variable was added, false otherwise
|
||||
bool VariableLinkedList::insert(string name, double value)
|
||||
{
|
||||
// Ensure there is space
|
||||
if (count == maxCount)
|
||||
return false;
|
||||
|
||||
// Ensure the variable does not exist
|
||||
VariableNode *s = this->search(name);
|
||||
if (s != nullptr)
|
||||
return false;
|
||||
|
||||
// Insert a new VariableNode into the head.
|
||||
head = new VariableNode(name, value, head);
|
||||
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Remove the variable with name from the linked list
|
||||
/// @param name The name of the variable to remove
|
||||
/// @return True if removed, false otherwise
|
||||
bool VariableLinkedList::remove(string name)
|
||||
{
|
||||
// Root node must be handled in a seperate case
|
||||
if (head != nullptr && head->getName() == name)
|
||||
{
|
||||
VariableNode *temp = head->getNext();
|
||||
delete head;
|
||||
head = temp;
|
||||
count --;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Search for the node before the one we want to remove.
|
||||
VariableNode *currentIndex = this->head;
|
||||
while (currentIndex != nullptr && currentIndex->getNext() != nullptr &&
|
||||
currentIndex->getNext()->getName() != name)
|
||||
currentIndex = currentIndex->getNext();
|
||||
|
||||
// currentIndex will be null if the index does not exist.
|
||||
if (currentIndex == nullptr || currentIndex->getNext() == nullptr)
|
||||
return false;
|
||||
|
||||
VariableNode *temp = currentIndex->getNext()->getNext();
|
||||
delete currentIndex->getNext();
|
||||
count--;
|
||||
currentIndex->setNext(temp);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Search for the variable with the given name
|
||||
/// @param name The name of the variable to search for
|
||||
/// @return A pointer to a valid VariableNode if the node exists, nullptr otherwise
|
||||
VariableNode *VariableLinkedList::search(string name)
|
||||
{
|
||||
VariableNode *currentIndex = this->head;
|
||||
while (currentIndex != nullptr)
|
||||
{
|
||||
if (currentIndex->getName() == name)
|
||||
{
|
||||
return currentIndex;
|
||||
}
|
||||
currentIndex = currentIndex->getNext();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
22
P1/VariableLinkedList.h
Normal file
22
P1/VariableLinkedList.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef VARIABLELINKEDLIST_H
|
||||
#define VARIABLELINKEDLIST_H
|
||||
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include "VariableNode.h"
|
||||
|
||||
class VariableLinkedList
|
||||
{
|
||||
public:
|
||||
bool insert(std::string name, double value);
|
||||
VariableNode *search(std::string name);
|
||||
bool remove(std::string name);
|
||||
VariableLinkedList(int cap);
|
||||
~VariableLinkedList();
|
||||
|
||||
private:
|
||||
VariableNode *head;
|
||||
int count;
|
||||
int maxCount;
|
||||
};
|
||||
#endif
|
||||
44
P1/VariableNode.cpp
Normal file
44
P1/VariableNode.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "VariableNode.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
VariableNode::VariableNode(std::string name, double value, VariableNode *next)
|
||||
{
|
||||
this->name = name;
|
||||
this->value = value;
|
||||
this->next = next;
|
||||
}
|
||||
|
||||
string VariableNode::getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
double VariableNode::getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void VariableNode::setValue(double value)
|
||||
{
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
void VariableNode::setNext(VariableNode *next)
|
||||
{
|
||||
this->next = next; // Be careful when calling setNext, or we could have a memory leak.
|
||||
}
|
||||
|
||||
VariableNode *VariableNode::getNext()
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
/// @brief Delete all children nodes of this element
|
||||
void VariableNode::DestroyAll()
|
||||
{
|
||||
if (this->next != nullptr)
|
||||
this->next->DestroyAll();
|
||||
|
||||
delete this;
|
||||
}
|
||||
26
P1/VariableNode.h
Normal file
26
P1/VariableNode.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef VARIABLENODE_H
|
||||
#define VARIABLENODE_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
class VariableNode
|
||||
{
|
||||
public:
|
||||
std::string getName();
|
||||
|
||||
double getValue();
|
||||
void setValue(double value);
|
||||
|
||||
VariableNode *getNext();
|
||||
void setNext(VariableNode *next);
|
||||
|
||||
VariableNode(std::string name, double value, VariableNode *next);
|
||||
|
||||
void DestroyAll();
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
double value;
|
||||
VariableNode *next;
|
||||
};
|
||||
#endif
|
||||
92
P1/test.cpp
Normal file
92
P1/test.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <iostream>
|
||||
#include "Calculator.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main ()
|
||||
{
|
||||
string cmd;
|
||||
Calculator *calc = nullptr;
|
||||
|
||||
while (cin >> cmd)
|
||||
{
|
||||
if (cmd == "CRT")
|
||||
{
|
||||
int N;
|
||||
cin >> N;
|
||||
|
||||
if (calc != nullptr)
|
||||
delete calc;
|
||||
calc = new Calculator(N);
|
||||
|
||||
cout << "success" << endl;
|
||||
}
|
||||
else if (cmd == "DEF")
|
||||
{
|
||||
string name;
|
||||
double val;
|
||||
|
||||
cin >> name;
|
||||
cin >> val;
|
||||
|
||||
if (calc->define(name, val))
|
||||
{
|
||||
cout << "success" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "failure" << endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "ADD" || cmd == "SUB")
|
||||
{
|
||||
string v1;
|
||||
string v2;
|
||||
string out;
|
||||
|
||||
cin >> v1;
|
||||
cin >> v2;
|
||||
cin >> out;
|
||||
|
||||
function<double(double, double)> operation;
|
||||
if (cmd == "ADD")
|
||||
operation = [](double d1, double d2) {return d1 + d2;};
|
||||
else
|
||||
operation = [](double d1, double d2) {return d1 - d2;};
|
||||
|
||||
if (calc->performOperation(v1, v2, out, operation))
|
||||
{
|
||||
cout << "success" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "failure" << endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "REM")
|
||||
{
|
||||
string name;
|
||||
|
||||
cin >> name;
|
||||
|
||||
if (calc->remove(name))
|
||||
cout << "success" << endl;
|
||||
else
|
||||
cout << "failure" << endl;
|
||||
}
|
||||
else if (cmd == "PRT")
|
||||
{
|
||||
string name;
|
||||
|
||||
cin >> name;
|
||||
|
||||
calc->print(name);
|
||||
}
|
||||
else if (cmd == "END")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete calc;
|
||||
}
|
||||
156
P2/ChainingHashTable.cpp
Normal file
156
P2/ChainingHashTable.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "ChainingHashTable.h"
|
||||
#include "Process.h"
|
||||
|
||||
ChainingHashTable::ChainingHashTable(int size)
|
||||
{
|
||||
processList = new std::vector<Process *>[size];
|
||||
maxCount = size;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
ChainingHashTable::~ChainingHashTable()
|
||||
{
|
||||
for (int i = 0; i < maxCount; i++)
|
||||
{
|
||||
for (int j = 0; j < processList[i].size(); j++)
|
||||
{
|
||||
delete processList[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
delete[] processList;
|
||||
}
|
||||
|
||||
/// @brief Insert a process into the hash table
|
||||
/// @param p the process to insert
|
||||
/// @return true if insertion was successful, false otherwise
|
||||
bool ChainingHashTable::Insert(Process *p)
|
||||
{
|
||||
if (count >= maxCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int hashedIndex = p->getPid() % maxCount;
|
||||
|
||||
int indexSize = processList[hashedIndex].size();
|
||||
|
||||
if (indexSize == 0)
|
||||
{
|
||||
processList[hashedIndex].emplace_back(p);
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// attempt to insert in the middle of the vector
|
||||
for (int i = 0; i < indexSize; i++)
|
||||
{
|
||||
if (processList[hashedIndex][i]->getPid() == p->getPid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// store in descending order (9, 8, 7,...)
|
||||
if (processList[hashedIndex][i]->getPid() < p->getPid())
|
||||
{
|
||||
processList[hashedIndex].insert(processList[hashedIndex].begin() + i, p);
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// insert at the end of the vector if we have to
|
||||
processList[hashedIndex].emplace_back(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Search the hash table for the PID
|
||||
/// @param PID the PID to search the hash table for
|
||||
/// @return the index if in the hash table, or -1 otherwise
|
||||
int ChainingHashTable::Search(unsigned int PID)
|
||||
{
|
||||
int hashedIndex = PID % maxCount;
|
||||
|
||||
int indexSize = processList[hashedIndex].size();
|
||||
|
||||
for (int i = 0; i < indexSize; i++)
|
||||
{
|
||||
if (processList[hashedIndex][i]->getPid() == PID)
|
||||
{
|
||||
return hashedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// @brief Get a pointer to the process with PID
|
||||
/// @param PID the PID to look for
|
||||
/// @return a pointer to the process, or nullptr if the process does not exist
|
||||
Process *ChainingHashTable::Get(unsigned int PID)
|
||||
{
|
||||
int hashedIndex = PID % maxCount;
|
||||
|
||||
int indexSize = processList[hashedIndex].size();
|
||||
|
||||
for (int i = 0; i < indexSize; i++)
|
||||
{
|
||||
if (processList[hashedIndex][i]->getPid() == PID)
|
||||
{
|
||||
return processList[hashedIndex][i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// @brief Remove a process from the hash table with a given PID
|
||||
/// @param PID the PID of the process to remove
|
||||
/// @return true if the process was removed, false otherwise
|
||||
bool ChainingHashTable::Remove(unsigned int PID)
|
||||
{
|
||||
int hashedIndex = PID % maxCount;
|
||||
|
||||
int indexSize = processList[hashedIndex].size();
|
||||
|
||||
for (int i = 0; i < indexSize; i++)
|
||||
{
|
||||
if (processList[hashedIndex][i]->getPid() == PID)
|
||||
{
|
||||
delete processList[hashedIndex][i];
|
||||
processList[hashedIndex].erase(processList[hashedIndex].begin() + i);
|
||||
count--;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief Print out the value of the chain at index m
|
||||
/// @param m the index to print the chain of
|
||||
void ChainingHashTable::Print(unsigned int m)
|
||||
{
|
||||
if (m >= maxCount)
|
||||
{
|
||||
std::cout << "chain is empty" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int indexSize = processList[m].size();
|
||||
|
||||
for (int i = 0; i < indexSize; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
std::cout << " ";
|
||||
|
||||
std::cout << processList[m][i]->getPid();
|
||||
}
|
||||
|
||||
if (indexSize < 1)
|
||||
{
|
||||
std::cout << "chain is empty";
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
23
P2/ChainingHashTable.h
Normal file
23
P2/ChainingHashTable.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef CHAININGHASHTABLE_H
|
||||
#define CHAININGHASHTABLE_H
|
||||
|
||||
#include <vector>
|
||||
#include "Process.h"
|
||||
#include "HashTable.h"
|
||||
|
||||
class ChainingHashTable : public HashTable
|
||||
{
|
||||
public:
|
||||
bool Insert(Process *p);
|
||||
int Search(unsigned int PID);
|
||||
Process *Get(unsigned int PID);
|
||||
bool Remove(unsigned int PID);
|
||||
void Print(unsigned int m);
|
||||
|
||||
ChainingHashTable(int size);
|
||||
~ChainingHashTable();
|
||||
|
||||
private:
|
||||
std::vector<Process *> *processList;
|
||||
};
|
||||
#endif
|
||||
177
P2/DoubleHashTable.cpp
Normal file
177
P2/DoubleHashTable.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
#include "DoubleHashTable.h"
|
||||
#include "Process.h"
|
||||
|
||||
DoubleHashTable::DoubleHashTable(int size)
|
||||
{
|
||||
processList = new Process *[size];
|
||||
maxCount = size;
|
||||
count = 0;
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
processList[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DoubleHashTable::~DoubleHashTable()
|
||||
{
|
||||
for (int i = 0; i < maxCount; i++)
|
||||
{
|
||||
if (processList[i] != nullptr)
|
||||
delete processList[i];
|
||||
}
|
||||
|
||||
delete[] processList;
|
||||
}
|
||||
|
||||
/// @brief Insert a process into the hash table
|
||||
/// @param p pointer to the process to insert
|
||||
/// @return true if successful, false otherwise
|
||||
bool DoubleHashTable::Insert(Process *p)
|
||||
{
|
||||
if (count >= maxCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Continually hash until we have reached a nullpointer, -1, or the end
|
||||
int emptyIndex = -1;
|
||||
for (int i = 0; i < maxCount; i++)
|
||||
{
|
||||
unsigned int hashedIndex = HashIndex(p->getPid(), i);
|
||||
|
||||
// If we have reached a nullptr, and have not seen any empty slots before
|
||||
if (processList[hashedIndex] == nullptr && emptyIndex == -1)
|
||||
{
|
||||
// Replace the nullpointer with the process
|
||||
processList[hashedIndex] = p;
|
||||
return true;
|
||||
}
|
||||
// If we have reached a nullpointer and have seen an empty slot before
|
||||
else if (processList[hashedIndex] == nullptr && emptyIndex != -1)
|
||||
{
|
||||
// Replace the -1 with the process
|
||||
hashedIndex = HashIndex(p->getPid(), emptyIndex);
|
||||
delete processList[hashedIndex];
|
||||
processList[hashedIndex] = p;
|
||||
return true;
|
||||
}
|
||||
// If we find a process with the same PID already, exit
|
||||
else if (processList[hashedIndex]->getPid() == p->getPid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// If we have found a slot of -1
|
||||
else if (processList[hashedIndex]->getStartingIndex() == -1 && emptyIndex == -1)
|
||||
{
|
||||
// If we can insert in the empty slot (have reached the end)
|
||||
emptyIndex = i;
|
||||
if (!(i + 1 < maxCount))
|
||||
{
|
||||
delete processList[hashedIndex];
|
||||
processList[hashedIndex] = p;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert into the empty slot - theoretically we do not need the code in the if statement of the last else if clause, but it works...
|
||||
if (emptyIndex != -1)
|
||||
{
|
||||
unsigned int hashedIndex = HashIndex(p->getPid(), emptyIndex);
|
||||
delete processList[hashedIndex];
|
||||
processList[hashedIndex] = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief Search the hash table for the given PID
|
||||
/// @param PID the pid to search for
|
||||
/// @return the index of the process, or -1 if the process does not exist
|
||||
int DoubleHashTable::Search(unsigned int PID)
|
||||
{
|
||||
for (int i = 0; i < maxCount; i++)
|
||||
{
|
||||
int hashedIndex = HashIndex(PID, i);
|
||||
|
||||
if (hashedIndex >= maxCount || processList[hashedIndex] == nullptr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (processList[hashedIndex]->getPid() == PID)
|
||||
{
|
||||
return hashedIndex;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// @brief Search the hash table for the given PID, and return a pointer to the process object
|
||||
/// @param PID the pid to search for
|
||||
/// @return A valid process object if it exists, or a nullpointer otherwise
|
||||
Process *DoubleHashTable::Get(unsigned int PID)
|
||||
{
|
||||
for (int i = 0; i < maxCount; i++)
|
||||
{
|
||||
int hashedIndex = HashIndex(PID, i);
|
||||
|
||||
if (hashedIndex >= maxCount || processList[hashedIndex] == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else if (processList[hashedIndex]->getPid() == PID)
|
||||
{
|
||||
return processList[hashedIndex];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// @brief Remove a process object from the hash table
|
||||
/// @param PID the PID of the process to remove
|
||||
/// @return true if the process was successfully removed, false otherwise
|
||||
bool DoubleHashTable::Remove(unsigned int PID)
|
||||
{
|
||||
for (int i = 0; i < maxCount; i++)
|
||||
{
|
||||
int hashedIndex = HashIndex(PID, i);
|
||||
|
||||
if (hashedIndex >= maxCount || processList[hashedIndex] == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (processList[hashedIndex]->getPid() == PID)
|
||||
{
|
||||
delete processList[hashedIndex];
|
||||
processList[hashedIndex] = new Process(0, -1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief Compute the hash of k and i.
|
||||
/// @param k the k value to hash (PID)
|
||||
/// @param i the i value to hash (index)
|
||||
/// @return the hashed value
|
||||
int DoubleHashTable::HashIndex(unsigned int k, int i)
|
||||
{
|
||||
unsigned int h1 = k % maxCount;
|
||||
unsigned int h2 = (int)std::floor(k / maxCount) % maxCount;
|
||||
|
||||
if (h2 % 2 == 0)
|
||||
h2++;
|
||||
|
||||
return (h1 + i * h2) % maxCount;
|
||||
}
|
||||
|
||||
void DoubleHashTable::Print(unsigned int m)
|
||||
{
|
||||
// Not implemented
|
||||
}
|
||||
24
P2/DoubleHashTable.h
Normal file
24
P2/DoubleHashTable.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef DOUBLEHASHTABLE_H
|
||||
#define DOUBLEHASHTABLE_H
|
||||
|
||||
#include <vector>
|
||||
#include "Process.h"
|
||||
#include "HashTable.h"
|
||||
|
||||
class DoubleHashTable : public HashTable
|
||||
{
|
||||
public:
|
||||
bool Insert(Process *p);
|
||||
int Search(unsigned int PID);
|
||||
Process *Get(unsigned int PID);
|
||||
bool Remove(unsigned int PID);
|
||||
void Print(unsigned int m);
|
||||
|
||||
DoubleHashTable(int size);
|
||||
~DoubleHashTable();
|
||||
|
||||
private:
|
||||
Process **processList;
|
||||
int HashIndex(unsigned int k, int i);
|
||||
};
|
||||
#endif
|
||||
20
P2/HashTable.h
Normal file
20
P2/HashTable.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef HASHTABLE_H
|
||||
#define HASHTABLE_H
|
||||
|
||||
#include <vector>
|
||||
#include "Process.h"
|
||||
|
||||
class HashTable
|
||||
{
|
||||
public:
|
||||
virtual bool Insert(Process *p) = 0;
|
||||
virtual int Search(unsigned int PID) = 0;
|
||||
virtual Process *Get(unsigned int PID) = 0;
|
||||
virtual bool Remove(unsigned int PID) = 0;
|
||||
virtual void Print(unsigned int m) = 0;
|
||||
|
||||
protected:
|
||||
int maxCount;
|
||||
int count;
|
||||
};
|
||||
#endif
|
||||
2
P2/Makefile
Normal file
2
P2/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
all: test.cpp ChainingHashTable.cpp DoubleHashTable.cpp Process.cpp VirtualMemory.cpp
|
||||
g++ -std=c++11 test.cpp ChainingHashTable.cpp DoubleHashTable.cpp Process.cpp VirtualMemory.cpp
|
||||
17
P2/Process.cpp
Normal file
17
P2/Process.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "Process.h"
|
||||
|
||||
Process::Process(unsigned int PID, int startingIndex)
|
||||
{
|
||||
this->PID = PID;
|
||||
this->startingIndex = startingIndex;
|
||||
}
|
||||
|
||||
unsigned int Process::getPid()
|
||||
{
|
||||
return this->PID;
|
||||
}
|
||||
|
||||
int Process::getStartingIndex()
|
||||
{
|
||||
return this->startingIndex;
|
||||
}
|
||||
16
P2/Process.h
Normal file
16
P2/Process.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef PROCESS_H
|
||||
#define PROCESS_H
|
||||
|
||||
class Process
|
||||
{
|
||||
public:
|
||||
unsigned int getPid();
|
||||
int getStartingIndex();
|
||||
|
||||
Process(unsigned int PID, int startingIndex);
|
||||
|
||||
private:
|
||||
unsigned int PID;
|
||||
int startingIndex;
|
||||
};
|
||||
#endif
|
||||
136
P2/VirtualMemory.cpp
Normal file
136
P2/VirtualMemory.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "VirtualMemory.h"
|
||||
#include "ChainingHashTable.h"
|
||||
#include "DoubleHashTable.h"
|
||||
|
||||
VirtualMemory::VirtualMemory(int n, int p, bool chaining)
|
||||
{
|
||||
if (chaining)
|
||||
{
|
||||
ht = new ChainingHashTable(n / p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ht = new DoubleHashTable(n / p);
|
||||
}
|
||||
|
||||
this->chaining = chaining;
|
||||
this->memorySize = n;
|
||||
this->pageSize = p;
|
||||
this->memory = new int[n];
|
||||
|
||||
// push the indices onto the free memory
|
||||
for (int i = 0; i < n / p; i++)
|
||||
{
|
||||
freeMemory.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
VirtualMemory::~VirtualMemory()
|
||||
{
|
||||
if (chaining)
|
||||
{
|
||||
delete (ChainingHashTable *)ht;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete (DoubleHashTable *)ht;
|
||||
}
|
||||
|
||||
delete[] memory;
|
||||
}
|
||||
|
||||
/// @brief Allocate memory for process PID
|
||||
/// @param PID the PID to allocate memory for
|
||||
/// @return true if successful, false otherwise
|
||||
bool VirtualMemory::Insert(unsigned int PID)
|
||||
{
|
||||
if (freeMemory.size() <= 0)
|
||||
return false;
|
||||
|
||||
int memoryIndex = freeMemory.back();
|
||||
freeMemory.pop_back();
|
||||
|
||||
Process *p = new Process(PID, memoryIndex);
|
||||
if (!ht->Insert(p))
|
||||
{
|
||||
delete p;
|
||||
freeMemory.push_back(memoryIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Search the hash table for the index of PID
|
||||
/// @param PID the PID of the process to search for
|
||||
/// @return the index of the process object, -1 if the object does not exist
|
||||
int VirtualMemory::Search(unsigned int PID)
|
||||
{
|
||||
return ht->Search(PID);
|
||||
}
|
||||
|
||||
/// @brief Write to a process's memory
|
||||
/// @param PID The PID of the memory to write to
|
||||
/// @param addr The virtual address of the memory to write to
|
||||
/// @param x The value to write into memory
|
||||
/// @return true if successful, false otherwise
|
||||
bool VirtualMemory::Write(unsigned int PID, int addr, int x)
|
||||
{
|
||||
if (addr >= pageSize || addr < 0)
|
||||
return false;
|
||||
|
||||
Process *p = ht->Get(PID);
|
||||
|
||||
// if we do not have any memory allocated to PID
|
||||
if (p == nullptr)
|
||||
return false;
|
||||
|
||||
memory[p->getStartingIndex() * pageSize + addr] = x;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Read the memory
|
||||
/// @param PID The PID of the process to read memory of
|
||||
/// @param addr The virtual address of memory to read from
|
||||
void VirtualMemory::Read(unsigned int PID, int addr)
|
||||
{
|
||||
if (addr >= pageSize)
|
||||
{
|
||||
std::cout << "failure" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
Process *p = ht->Get(PID);
|
||||
// if we do not have any memory allocated to PID
|
||||
if (p == nullptr)
|
||||
{
|
||||
std::cout << "failure" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << addr << " " << memory[p->getStartingIndex() * pageSize + addr] << std::endl;
|
||||
}
|
||||
|
||||
/// @brief Deallocate memory from process PID.
|
||||
/// @param PID The PID of the process to dealocate memory from
|
||||
/// @return true if successful, false otherwise
|
||||
bool VirtualMemory::Delete(unsigned int PID)
|
||||
{
|
||||
Process *p = ht->Get(PID);
|
||||
|
||||
if (p == nullptr)
|
||||
return false;
|
||||
|
||||
freeMemory.push_back(p->getStartingIndex());
|
||||
|
||||
return ht->Remove(PID);
|
||||
}
|
||||
|
||||
/// @brief Print the chain of the hash table at index m
|
||||
/// @param m the index of the chain to print
|
||||
void VirtualMemory::Print(int m)
|
||||
{
|
||||
ht->Print(m);
|
||||
}
|
||||
30
P2/VirtualMemory.h
Normal file
30
P2/VirtualMemory.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef VIRTUALMEMORY_H
|
||||
#define VIRTUALMEMORY_H
|
||||
|
||||
#include "Process.h"
|
||||
#include "HashTable.h"
|
||||
|
||||
class VirtualMemory
|
||||
{
|
||||
public:
|
||||
VirtualMemory(int n, int p, bool chaining);
|
||||
~VirtualMemory();
|
||||
|
||||
bool Insert(unsigned int PID);
|
||||
int Search(unsigned int PID);
|
||||
|
||||
bool Write(unsigned int PID, int addr, int x);
|
||||
void Read(unsigned int PID, int addr);
|
||||
|
||||
bool Delete(unsigned int PID);
|
||||
void Print(int m);
|
||||
|
||||
private:
|
||||
HashTable *ht;
|
||||
int memorySize;
|
||||
int pageSize;
|
||||
int *memory;
|
||||
std::vector<int> freeMemory;
|
||||
bool chaining;
|
||||
};
|
||||
#endif
|
||||
103
P2/test.cpp
Normal file
103
P2/test.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "VirtualMemory.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
string cmd;
|
||||
VirtualMemory *vm = nullptr;
|
||||
bool chaining = true;
|
||||
|
||||
while (cin >> cmd)
|
||||
{
|
||||
if (cmd == "OPEN")
|
||||
{
|
||||
chaining = false;
|
||||
}
|
||||
else if (cmd == "ORDERED")
|
||||
{
|
||||
chaining = true;
|
||||
}
|
||||
if (cmd == "M")
|
||||
{
|
||||
int N;
|
||||
int P;
|
||||
cin >> N;
|
||||
cin >> P;
|
||||
|
||||
vm = new VirtualMemory(N, P, chaining);
|
||||
|
||||
cout << "success" << endl;
|
||||
}
|
||||
else if (cmd == "INSERT")
|
||||
{
|
||||
unsigned int PID;
|
||||
cin >> PID;
|
||||
|
||||
if (vm->Insert(PID))
|
||||
cout << "success" << endl;
|
||||
else
|
||||
cout << "failure" << endl;
|
||||
}
|
||||
else if (cmd == "SEARCH")
|
||||
{
|
||||
unsigned int PID;
|
||||
cin >> PID;
|
||||
|
||||
int ret = vm->Search(PID);
|
||||
if (ret == -1)
|
||||
cout << "not found" << endl;
|
||||
else
|
||||
cout << "found " << PID << " in " << ret << endl;
|
||||
}
|
||||
else if (cmd == "WRITE")
|
||||
{
|
||||
unsigned int PID;
|
||||
int ADDR;
|
||||
int x;
|
||||
|
||||
cin >> PID;
|
||||
cin >> ADDR;
|
||||
cin >> x;
|
||||
|
||||
if (vm->Write(PID, ADDR, x))
|
||||
cout << "success" << endl;
|
||||
else
|
||||
cout << "failure" << endl;
|
||||
}
|
||||
else if (cmd == "READ")
|
||||
{
|
||||
unsigned int PID;
|
||||
int ADDR;
|
||||
|
||||
cin >> PID;
|
||||
cin >> ADDR;
|
||||
|
||||
vm->Read(PID, ADDR);
|
||||
}
|
||||
else if (cmd == "DELETE")
|
||||
{
|
||||
unsigned int PID;
|
||||
cin >> PID;
|
||||
|
||||
if (vm->Delete(PID))
|
||||
cout << "success" << endl;
|
||||
else
|
||||
cout << "failure" << endl;
|
||||
}
|
||||
else if (cmd == "PRINT")
|
||||
{
|
||||
int m;
|
||||
cin >> m;
|
||||
|
||||
vm->Print(m);
|
||||
}
|
||||
else if (cmd == "END")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete vm;
|
||||
}
|
||||
2
P3/Makefile
Normal file
2
P3/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
all: trietest.cpp Trie.cpp
|
||||
g++ -std=c++11 trietest.cpp Trie.cpp
|
||||
218
P3/Trie.cpp
Normal file
218
P3/Trie.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
#include "Trie.h"
|
||||
#include "illegal_exception.h"
|
||||
|
||||
Trie::Trie()
|
||||
{
|
||||
children = new Trie *[MAX_SLOTS];
|
||||
isEnd = false;
|
||||
for (int i = 0; i < MAX_SLOTS; i++)
|
||||
{
|
||||
children[i] = nullptr;
|
||||
}
|
||||
count = 0;
|
||||
}
|
||||
|
||||
Trie::~Trie()
|
||||
{
|
||||
delete[] children;
|
||||
}
|
||||
|
||||
/// @brief Wrapper function to recursively insert string s into the trie.
|
||||
/// @param s The string to insert into the trie.
|
||||
/// @return True if the string was inserted, false otherwise.
|
||||
bool Trie::Insert(std::string s)
|
||||
{
|
||||
// Wrapper function is needed to meet illegal_exception criteria without having O(n^2) runtime (recursive function).
|
||||
for (int i = 0; i < s.length(); i++)
|
||||
{
|
||||
if (s[i] < ASCII_FACTOR || s[i] > ASCII_UPPER)
|
||||
{
|
||||
throw illegal_exception();
|
||||
}
|
||||
}
|
||||
return PerformInsert(s);
|
||||
}
|
||||
|
||||
/// @brief Recursive function to insert string s into the trie.
|
||||
/// @param s The string to insert into the trie.
|
||||
/// @return True if the string was inserted successfully, false otherwise.
|
||||
bool Trie::PerformInsert(std::string s)
|
||||
{
|
||||
if (s.length() > 0) // Add until there are no more characters.
|
||||
{
|
||||
char c = s.at(0);
|
||||
// Create the new trie if it does not exist. This condition will never be true if the word cannot be inserted.
|
||||
if (children[c - ASCII_FACTOR] == nullptr)
|
||||
children[c - ASCII_FACTOR] = new Trie();
|
||||
|
||||
// Recursively insert, checking if the previous insertion was successful (if so, increment count).
|
||||
if (children[c - ASCII_FACTOR]->PerformInsert(s.substr(1)))
|
||||
{
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// If there are no characters and we have not reached a word end then the word is not already added.
|
||||
else if (!this->isEnd)
|
||||
{
|
||||
this->isEnd = true;
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
return false; // If the word is already in the trie, return false.
|
||||
}
|
||||
|
||||
/// @brief Wrapper function to remove an element from the trie.
|
||||
/// @param s The string to remove from the trie.
|
||||
/// @return True if the element was removed successfully, false otherwise.
|
||||
bool Trie::Remove(std::string s)
|
||||
{
|
||||
// Achieve O(n) runtime using wrapper function.
|
||||
for (int i = 0; i < s.length(); i++)
|
||||
{
|
||||
if (s[i] < ASCII_FACTOR || s[i] > ASCII_UPPER)
|
||||
{
|
||||
throw illegal_exception();
|
||||
}
|
||||
}
|
||||
return PerformRemove(s);
|
||||
}
|
||||
|
||||
/// @brief Recursively remove string s from the trie.
|
||||
/// @param s The string to remove from the trie.
|
||||
/// @return True if the string was removed, false otherwise.
|
||||
bool Trie::PerformRemove(std::string s)
|
||||
{
|
||||
if (s.length() > 0) // Remove until there are no more characters to remove.
|
||||
{
|
||||
// If we have reached a trie that does not have the correct child, we cannot remove the word.
|
||||
char c = s.at(0);
|
||||
if (children[c - ASCII_FACTOR] == nullptr)
|
||||
return false;
|
||||
|
||||
// Recursively remove the remaining bit of the word. Subtracting from the count if successful.
|
||||
if (children[c - ASCII_FACTOR]->PerformRemove(s.substr(1)))
|
||||
{
|
||||
count--;
|
||||
|
||||
// Free any child tries that have a count of 0. These are guaranteed to have no children.
|
||||
for (int i = 0; i < MAX_SLOTS; i++)
|
||||
{
|
||||
if (children[i] != nullptr && children[i]->IsEmpty())
|
||||
{
|
||||
delete children[i];
|
||||
children[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return true; // If previous removes were successful, this remove is also successful.
|
||||
}
|
||||
}
|
||||
// If we have reached the end of the word, we can succesfully remove it from the trie.
|
||||
else if (this->isEnd)
|
||||
{
|
||||
this->isEnd = false;
|
||||
count--;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // When we are out of characters, but did not find a word end, cannot remove.
|
||||
}
|
||||
|
||||
/// @brief Determine if the trie is empty.
|
||||
/// @return True if the trie is empty, false otherwise.
|
||||
bool Trie::IsEmpty()
|
||||
{
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
/// @brief Empty the trie.
|
||||
void Trie::Clear()
|
||||
{
|
||||
// We do not need to worry about dangling pointers, since everything is being deleted in order.
|
||||
for (int i = 0; i < MAX_SLOTS; i++)
|
||||
{
|
||||
if (children[i] != nullptr)
|
||||
children[i]->Clear(); // Recursively delete any non-null pointer children.
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
/// @brief Perform a depth first search on the trie for string s, outputting the result by performing in place modification of the vector out.
|
||||
/// @param out
|
||||
/// @param s
|
||||
void Trie::DepthFirstSearch(std::vector<std::string> *out, std::string s)
|
||||
{
|
||||
if (isEnd)
|
||||
out->push_back(s); // If we have reached the end, put the word into the output
|
||||
|
||||
// Recursively search children nodes, in order from A-Z.
|
||||
for (int i = 0; i < MAX_SLOTS; i++)
|
||||
{
|
||||
if (children[i] != nullptr)
|
||||
children[i]->DepthFirstSearch(out, s + (char)(i + ASCII_FACTOR));
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Get the number of words in the trie.
|
||||
/// @return An integer of the number of words in the trie.
|
||||
int Trie::Size()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
/// @brief Wrapper function to count the number of suffixes for a given string s.
|
||||
/// @param s
|
||||
/// @return
|
||||
int Trie::CountSuffixes(std::string s)
|
||||
{
|
||||
for (int i = 0; i < s.length(); i++)
|
||||
{
|
||||
if (s[i] < ASCII_FACTOR || s[i] > ASCII_UPPER)
|
||||
{
|
||||
throw illegal_exception();
|
||||
}
|
||||
}
|
||||
return PerformCountSuffixes(s);
|
||||
}
|
||||
|
||||
|
||||
int Trie::PerformCountSuffixes(std::string s)
|
||||
{
|
||||
if (s.empty())
|
||||
return count;
|
||||
|
||||
char c = s.at(0);
|
||||
int index = c - ASCII_FACTOR;
|
||||
|
||||
if (children[index] != nullptr)
|
||||
return children[index]->PerformCountSuffixes(s.substr(1));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Trie::SpellCheck(std::vector<std::string> *out, std::string check, std::string s)
|
||||
{
|
||||
if (check.empty() && isEnd)
|
||||
return true;
|
||||
else if (check.empty())
|
||||
return false;
|
||||
|
||||
char c = check.at(0);
|
||||
int index = c - ASCII_FACTOR;
|
||||
;
|
||||
if (children[index] != nullptr)
|
||||
{
|
||||
if (children[index]->SpellCheck(out, check.substr(1), s + c))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
children[index]->DepthFirstSearch(out, s + c);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
33
P3/Trie.h
Normal file
33
P3/Trie.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef TRIE_H
|
||||
#define TRIE_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
class Trie
|
||||
{
|
||||
public:
|
||||
Trie();
|
||||
~Trie();
|
||||
bool Insert(std::string s);
|
||||
bool Remove(std::string s);
|
||||
void DepthFirstSearch(std::vector<std::string> *out, std::string s);
|
||||
bool IsEmpty();
|
||||
void Clear();
|
||||
int Size();
|
||||
int CountSuffixes(std::string s);
|
||||
bool SpellCheck(std::vector<std::string> *out, std::string check, std::string s);
|
||||
|
||||
private:
|
||||
const int MAX_SLOTS = 26;
|
||||
const int ASCII_FACTOR = 65;
|
||||
const int ASCII_UPPER = 90;
|
||||
int count;
|
||||
bool isEnd;
|
||||
Trie **children;
|
||||
|
||||
bool PerformInsert(std::string s);
|
||||
bool PerformRemove(std::string s);
|
||||
int PerformCountSuffixes(std::string s);
|
||||
};
|
||||
#endif
|
||||
8
P3/illegal_exception.h
Normal file
8
P3/illegal_exception.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef ILLEGAL_EXCEPTION_H
|
||||
#define ILLEGAL_EXCEPTION_H
|
||||
|
||||
#include <exception>
|
||||
|
||||
class illegal_exception : std::exception {};
|
||||
|
||||
#endif
|
||||
153
P3/trietest.cpp
Normal file
153
P3/trietest.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "Trie.h"
|
||||
#include <vector>
|
||||
#include "illegal_exception.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const string FILE_NAME = "corpus.txt";
|
||||
|
||||
void PrintVector(vector<string> *out)
|
||||
{
|
||||
for (int i = 0; i < out->size(); i++)
|
||||
{
|
||||
cout << (*out)[i];
|
||||
if (i < out->size() - 1)
|
||||
cout << " ";
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
string cmd;
|
||||
string addWord;
|
||||
ifstream fin(FILE_NAME);
|
||||
Trie *trie = new Trie();
|
||||
|
||||
while (cin >> cmd)
|
||||
{
|
||||
if (cmd == "load")
|
||||
{
|
||||
if (!fin.is_open())
|
||||
fin.open(FILE_NAME);
|
||||
|
||||
while (fin >> addWord)
|
||||
{
|
||||
trie->Insert(addWord);
|
||||
}
|
||||
|
||||
fin.close();
|
||||
cout << "success" << endl;
|
||||
}
|
||||
else if (cmd == "i")
|
||||
{
|
||||
string word;
|
||||
cin >> word;
|
||||
try
|
||||
{
|
||||
if (trie->Insert(word))
|
||||
cout << "success" << endl;
|
||||
else
|
||||
cout << "failure" << endl;
|
||||
}
|
||||
catch (illegal_exception e)
|
||||
{
|
||||
cout << "illegal argument" << endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "e")
|
||||
{
|
||||
string word;
|
||||
cin >> word;
|
||||
|
||||
try
|
||||
{
|
||||
if (trie->Remove(word))
|
||||
cout << "success" << endl;
|
||||
else
|
||||
cout << "failure" << endl;
|
||||
}
|
||||
catch (illegal_exception e)
|
||||
{
|
||||
cout << "illegal argument" << endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "clear")
|
||||
{
|
||||
trie->Clear();
|
||||
trie = new Trie();
|
||||
cout << "success" << endl;
|
||||
}
|
||||
else if (cmd == "size")
|
||||
{
|
||||
cout << "number of words is " << trie->Size() << endl;
|
||||
}
|
||||
else if (cmd == "empty")
|
||||
{
|
||||
if (trie->IsEmpty())
|
||||
cout << "empty 1" << endl;
|
||||
else
|
||||
cout << "empty 0" << endl;
|
||||
}
|
||||
else if (cmd == "spellcheck")
|
||||
{
|
||||
string word;
|
||||
cin >> word;
|
||||
|
||||
vector<string> out;
|
||||
|
||||
bool result = trie->SpellCheck(&out, word, "");
|
||||
|
||||
if (out.empty() && result)
|
||||
{
|
||||
cout << "correct" << endl;
|
||||
}
|
||||
else if (!result)
|
||||
{
|
||||
cout << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintVector(&out);
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "p")
|
||||
{
|
||||
vector<string> out;
|
||||
trie->DepthFirstSearch(&out, "");
|
||||
|
||||
PrintVector(&out);
|
||||
|
||||
if (out.size() > 0)
|
||||
cout << endl;
|
||||
|
||||
}
|
||||
|
||||
else if (cmd == "c")
|
||||
{
|
||||
string prefix;
|
||||
cin >> prefix;
|
||||
|
||||
try
|
||||
{
|
||||
int count = trie->CountSuffixes(prefix);
|
||||
|
||||
if (count != -1 && count != 0)
|
||||
cout << "count is " << count << endl;
|
||||
else
|
||||
cout << "not found" << endl;
|
||||
}
|
||||
catch (illegal_exception e)
|
||||
{
|
||||
cout << "illegal argument" << endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "exit")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
trie->Clear();
|
||||
}
|
||||
189
P4/Graph.cpp
Normal file
189
P4/Graph.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
#include "Graph.h"
|
||||
#include <limits.h>
|
||||
#include "PriorityQueue.h"
|
||||
#include "illegal_exception.h"
|
||||
|
||||
/// @brief Create a new graph
|
||||
/// @param maxCount The maximum number of elements the graph is required to store
|
||||
/// @param mst A flag to enable MST (enabling makes the runtime of the graph worse)
|
||||
Graph::Graph(int maxCount, bool mst)
|
||||
{
|
||||
vertexList.reserve(maxCount);
|
||||
if (!mst)
|
||||
pq = new PriorityQueue(maxCount);
|
||||
this->maxCount = maxCount;
|
||||
this->mstEnabled = mst;
|
||||
}
|
||||
|
||||
Graph::~Graph()
|
||||
{
|
||||
delete pq;
|
||||
}
|
||||
|
||||
/// @brief Insert an edge from vertex a to b, with weight w. When MST flag is true, it is invalid to pass in edges that already exist in the graph.
|
||||
/// @param a Vertex a
|
||||
/// @param b Vertex b
|
||||
/// @param weight The weight of the edge to insert
|
||||
/// @return True if successful, false otherwise
|
||||
/// @throws illegal_exception if given invalid input
|
||||
bool Graph::Insert(int a, int b, int weight)
|
||||
{
|
||||
// Check input validity
|
||||
if (a > 50000 || a < 1 || b > 50000 || b < 1 || weight < 1)
|
||||
{
|
||||
throw illegal_exception();
|
||||
}
|
||||
|
||||
// Check if the node already exists. Skip this check when the MST is disabled - allows efficient inserts for building tree.
|
||||
int count = adjacencyList[a].size();
|
||||
if (!mstEnabled)
|
||||
{
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int currentData = std::get<0>(adjacencyList[a][i]);
|
||||
if (currentData == b)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the b vertex to the adjacency list for a
|
||||
adjacencyList[a].push_back(std::make_tuple(b, weight));
|
||||
|
||||
// Add the vertex a to the vertexList, if a has never been added to the graph
|
||||
if (count == 0)
|
||||
vertexList.insert(vertexList.begin() + vertexList.size(), std::make_tuple(a, INT_MAX, -1));
|
||||
|
||||
// Add a vertex to the adjacency list for b, and insert b into vertexList if required
|
||||
count = adjacencyList[b].size();
|
||||
adjacencyList[b].push_back(std::make_tuple(a, weight));
|
||||
if (count == 0)
|
||||
vertexList.insert(vertexList.begin() + vertexList.size(), std::make_tuple(b, INT_MAX, -1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Delete vertex a from the graph.
|
||||
/// @param a The vertex to delete from the graph.
|
||||
/// @return True if successful, false otherwise.
|
||||
/// @throws illegal_exception if given invalid input.
|
||||
bool Graph::Delete(int a)
|
||||
{
|
||||
// Check input conditions
|
||||
if (a > 50000 || a < 1)
|
||||
{
|
||||
throw illegal_exception();
|
||||
}
|
||||
|
||||
// Ensure the vertex is in the graph
|
||||
int count = adjacencyList[a].size();
|
||||
if (count == 0)
|
||||
return false;
|
||||
|
||||
// Remove all references to the vertex in the adjacency lists of other vertices, and in the vertexList.
|
||||
while (count != 0)
|
||||
{
|
||||
std::tuple<int, int> lastData = adjacencyList[a][count - 1];
|
||||
adjacencyList[a].pop_back();
|
||||
|
||||
// Remove vertex from all adjacency lists
|
||||
for (int j = 0; j < adjacencyList[std::get<0>(lastData)].size(); j++)
|
||||
{
|
||||
if (std::get<0>(adjacencyList[std::get<0>(lastData)][j]) == a)
|
||||
{
|
||||
adjacencyList[std::get<0>(lastData)].erase(adjacencyList[std::get<0>(lastData)].begin() + j);
|
||||
}
|
||||
}
|
||||
|
||||
// If removing vertex a causes any adjacency lists to become empty, remove that vertex from the vertexList.
|
||||
if (adjacencyList[std::get<0>(lastData)].size() < 1)
|
||||
{
|
||||
for (int j = 0; j < vertexList.size(); j++)
|
||||
{
|
||||
if (std::get<0>(vertexList[j]) == std::get<0>(lastData))
|
||||
vertexList.erase(vertexList.begin() + j);
|
||||
}
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
|
||||
// Remove a from the vertex list.
|
||||
for (int i = 0; i < vertexList.size(); i++)
|
||||
{
|
||||
if (std::get<0>(vertexList[i]) == a)
|
||||
vertexList.erase(vertexList.begin() + i);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Get a vector containing the adjacent vertices to a
|
||||
/// @param a The vertex to check
|
||||
/// @return A vector of all vertices
|
||||
/// @throws illegal_exception if given invalid input.
|
||||
std::vector<std::tuple<int, int>> *Graph::GetAdjacent(int a)
|
||||
{
|
||||
if (a > 50000 || a < 1)
|
||||
{
|
||||
throw illegal_exception();
|
||||
}
|
||||
|
||||
return &adjacencyList[a];
|
||||
}
|
||||
|
||||
/// @brief Compute the MST of the graph
|
||||
/// @param out A vector to output the resulting MST edges in
|
||||
/// @return The cost of the MST
|
||||
int Graph::MST(std::vector<std::tuple<int, int, int>> *out)
|
||||
{
|
||||
// If there are no nodes, or somehow only one node.
|
||||
if (vertexList.size() < 2)
|
||||
return 0;
|
||||
|
||||
// When there is only one edge, that edge is the MST
|
||||
if (vertexList.size() < 3)
|
||||
{
|
||||
out->push_back(std::make_tuple(std::get<0>(vertexList[0]), std::get<0>(vertexList[1]), std::get<1>(adjacencyList[std::get<0>(vertexList[0])][0])));
|
||||
return std::get<1>(adjacencyList[std::get<0>(vertexList[0])][0]);
|
||||
}
|
||||
|
||||
// Attribution: Some of the Pseudocode used to write this function is from the CLRS textbook.
|
||||
int cost = 0;
|
||||
pq->Init(&vertexList);
|
||||
|
||||
// Apply Prim's Algorithm using a PriorityQueue.
|
||||
// Extract elements from the PQ until it is empty
|
||||
while (!pq->IsEmpty())
|
||||
{
|
||||
// Extract the element with the lowest weight
|
||||
std::tuple<int, int, int> u = pq->HeapExtractMin();
|
||||
|
||||
// Prevent insertion of first node (or any infinite weights).
|
||||
if (std::get<1>(u) != INT_MAX)
|
||||
{
|
||||
out->push_back(std::make_tuple(std::get<2>(u), std::get<0>(u), std::get<1>(u)));
|
||||
cost += std::get<1>(u);
|
||||
}
|
||||
|
||||
// Iterate through all of the adjacent vertices
|
||||
for (int i = 0; i < adjacencyList[std::get<0>(u)].size(); i++)
|
||||
{
|
||||
std::tuple<int, int> v = adjacencyList[std::get<0>(u)][i]; // The vertex being examined
|
||||
|
||||
// If the current path is better than the stored path, update it.
|
||||
if (pq->Contains(std::get<0>(v)) && std::get<1>(v) < pq->GetKey(std::get<0>(v)))
|
||||
{
|
||||
pq->Modify(std::get<0>(v), std::get<1>(v), std::get<0>(u));
|
||||
}
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
/// @brief Get the number of vertices in the graph
|
||||
/// @return The number of vertices in the graph
|
||||
int Graph::GetVertexCount()
|
||||
{
|
||||
return vertexList.size();
|
||||
}
|
||||
27
P4/Graph.h
Normal file
27
P4/Graph.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef TRIE_H
|
||||
#define TRIE_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include "PriorityQueue.h"
|
||||
|
||||
class Graph
|
||||
{
|
||||
public:
|
||||
Graph(int maxCount, bool mst);
|
||||
~Graph();
|
||||
bool Insert(int a, int b, int weight);
|
||||
bool Delete(int a);
|
||||
std::vector<std::tuple<int, int>> *GetAdjacent(int a);
|
||||
int GetVertexCount();
|
||||
int MST(std::vector<std::tuple<int, int, int>> *outList);
|
||||
|
||||
private:
|
||||
PriorityQueue *pq;
|
||||
std::vector<std::tuple<int, int>> adjacencyList[50001]; // An array of vectors of tuples <node2, weight>
|
||||
std::vector<std::tuple<int, int, int>> vertexList; // List of all vertices in the graph stored as <node1, inf, -1>
|
||||
int maxCount;
|
||||
bool mstEnabled;
|
||||
};
|
||||
#endif
|
||||
2
P4/Makefile
Normal file
2
P4/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
all: Test.cpp Graph.cpp PriorityQueue.cpp
|
||||
g++ -std=c++11 Test.cpp Graph.cpp PriorityQueue.cpp
|
||||
153
P4/PriorityQueue.cpp
Normal file
153
P4/PriorityQueue.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#include "PriorityQueue.h"
|
||||
#include <limits>
|
||||
|
||||
// Attribution: Some of the Pseudocode used to write these functions is from the CLRS textbook.
|
||||
|
||||
PriorityQueue::PriorityQueue(int maxCount)
|
||||
{
|
||||
count = 0;
|
||||
locations.reserve(maxCount);
|
||||
arr.reserve(maxCount);
|
||||
for (int i = 0; i < maxCount; i++)
|
||||
{
|
||||
locations[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Initialize the priority queue with the given vector of tuples. The tuples should be in the format: <vertex, weight, parent>
|
||||
/// @param vertexList The vector of tuples to insert into the priority queue.
|
||||
void PriorityQueue::Init(std::vector<std::tuple<int, int, int>> *vertexList)
|
||||
{
|
||||
count = vertexList->size();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
arr[i] = vertexList->at(i);
|
||||
locations[std::get<0>(vertexList->at(i))] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Modify the weight and/or the parent of vertex v
|
||||
/// @param v The vertex to modify (not the index in the priority queue)
|
||||
/// @param w The weight to set
|
||||
/// @param parent The parent to set
|
||||
/// @return True if successful, false otherwise
|
||||
bool PriorityQueue::Modify(int v, int w, int parent)
|
||||
{
|
||||
if (count < 1)
|
||||
return false;
|
||||
|
||||
int i = locations[v];
|
||||
if (i < 0)
|
||||
return false;
|
||||
|
||||
std::get<1>(arr[i]) = w;
|
||||
std::get<2>(arr[i]) = parent;
|
||||
while (i > 0 && std::get<1>(arr[Parent(i)]) > std::get<1>(arr[i]))
|
||||
{
|
||||
|
||||
Exchange(i, Parent(i));
|
||||
i = Parent(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Extract the smallest value from the priority queue (the topmost element, since this is a min pq).
|
||||
/// @return The element in the priority queue if not empty, or a tuple of all ints <-1, -1, -1> if empty
|
||||
std::tuple<int, int, int> PriorityQueue::HeapExtractMin()
|
||||
{
|
||||
// Signal no minimum element if there are no elements.
|
||||
if (IsEmpty())
|
||||
return std::make_tuple<int, int, int>(-1, -1, -1);
|
||||
|
||||
std::tuple<int, int, int> min = arr[0];
|
||||
|
||||
locations[std::get<0>(arr[count - 1])] = 0;
|
||||
locations[std::get<0>(min)] = -1;
|
||||
arr[0] = arr[count - 1];
|
||||
count--;
|
||||
MinHeapify(0);
|
||||
return min;
|
||||
}
|
||||
|
||||
/// @brief Run the MinHeapify algorithm on the pq.
|
||||
/// @param i The index (not the vertex).
|
||||
void PriorityQueue::MinHeapify(int i)
|
||||
{
|
||||
int l = Left(i);
|
||||
int r = Right(i);
|
||||
|
||||
int smallest = i;
|
||||
|
||||
if (l < count && std::get<1>(arr[l]) < std::get<1>(arr[i]))
|
||||
smallest = l;
|
||||
|
||||
if (r < count && std::get<1>(arr[r]) < std::get<1>(arr[smallest]))
|
||||
smallest = r;
|
||||
|
||||
if (smallest != i)
|
||||
{
|
||||
Exchange(i, smallest);
|
||||
MinHeapify(smallest);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Get a boolean value to determine if the priority queue is empty
|
||||
/// @return True if the priority queue is empty, false otherwise.
|
||||
bool PriorityQueue::IsEmpty()
|
||||
{
|
||||
return count < 1;
|
||||
}
|
||||
|
||||
/// @brief Check if the priority queue contains a vertex v.
|
||||
/// @param v The vertex (not index) to check.
|
||||
/// @return True if the vertex (not index) is contained in the priority queue, false otherwise.
|
||||
bool PriorityQueue::Contains(int v)
|
||||
{
|
||||
return locations[v] != -1;
|
||||
}
|
||||
|
||||
/// @brief Get the key (weight) of a vertex (not index) in the priority queue
|
||||
/// @param v The vertex (not index) to get the weight for
|
||||
/// @return The key (weight) of the vertex
|
||||
int PriorityQueue::GetKey(int v)
|
||||
{
|
||||
return std::get<1>(arr[locations[v]]);
|
||||
}
|
||||
|
||||
/// @brief Swap the elements of index a and index b (not the vertex number)
|
||||
/// @param a The index (not vertex) of the element to swap
|
||||
/// @param b The index (not vertex) of the element to swap
|
||||
void PriorityQueue::Exchange(int a, int b)
|
||||
{
|
||||
locations[std::get<0>(arr[a])] = b;
|
||||
locations[std::get<0>(arr[b])] = a;
|
||||
|
||||
std::tuple<int, int, int> temp = arr[a];
|
||||
arr[a] = arr[b];
|
||||
arr[b] = temp;
|
||||
}
|
||||
|
||||
/// @brief Given an index (not vertex), get the parent of that index (not vertex)
|
||||
/// @param i The index (not vertex) to get the parent of
|
||||
/// @return The index (not vertex) of the parent
|
||||
int PriorityQueue::Parent(int i)
|
||||
{
|
||||
return (i - 1) / 2;
|
||||
}
|
||||
|
||||
/// @brief Given an index (not vertex), get the left child of that index (not vertex)
|
||||
/// @param i The index (not vertex) to get the left child of
|
||||
/// @return The index (not vertex) of the left child
|
||||
int PriorityQueue::Left(int i)
|
||||
{
|
||||
return 2 * i + 1;
|
||||
}
|
||||
|
||||
/// @brief Given an index (not vertex), get the right child of that index (not vertex)
|
||||
/// @param i The index (not vertex) to get the right child of
|
||||
/// @return The index (not vertex) of the right child
|
||||
int PriorityQueue::Right(int i)
|
||||
{
|
||||
return 2 * i + 2;
|
||||
}
|
||||
31
P4/PriorityQueue.h
Normal file
31
P4/PriorityQueue.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef PRIORITYQUEUE_H
|
||||
#define PRIORITYQUEUE_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
class PriorityQueue
|
||||
{
|
||||
public:
|
||||
PriorityQueue(int maxCount);
|
||||
void Init(std::vector<std::tuple<int, int, int>> *vertexList);
|
||||
std::tuple<int, int, int> HeapExtractMin();
|
||||
bool Modify(int i, int w, int parent);
|
||||
bool Contains(int v);
|
||||
bool IsEmpty();
|
||||
int GetKey(int v);
|
||||
|
||||
private:
|
||||
int count;
|
||||
void Exchange(int a, int b);
|
||||
void MinHeapify(int i);
|
||||
int Parent(int i);
|
||||
int Left(int i);
|
||||
int Right(int i);
|
||||
std::vector<std::tuple<int, int, int>> arr; // The actual priority queue.
|
||||
std::vector<int> locations; // References for vertex -> PQ index. Allows indexing PQ in O(1) time.
|
||||
const int MAX_UNIQUE_KEYS = 50001;
|
||||
};
|
||||
|
||||
#endif
|
||||
180
P4/Test.cpp
Normal file
180
P4/Test.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "Graph.h"
|
||||
#include "illegal_exception.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const int MAX_NODE_COUNT = 50001;
|
||||
|
||||
int main()
|
||||
{
|
||||
string cmd;
|
||||
Graph *graph = new Graph(MAX_NODE_COUNT, false);
|
||||
bool mstModified = true;
|
||||
int prevCost = 0;
|
||||
std::vector<std::tuple<int, int, int>> prevOutput;
|
||||
|
||||
while (cin >> cmd)
|
||||
{
|
||||
if (cmd == "LOAD")
|
||||
{
|
||||
mstModified = true;
|
||||
string filename;
|
||||
cin >> filename;
|
||||
|
||||
ifstream fin(filename.c_str());
|
||||
|
||||
int count;
|
||||
fin >> count;
|
||||
|
||||
int n1;
|
||||
while (fin >> n1)
|
||||
{
|
||||
int n2;
|
||||
fin >> n2;
|
||||
int w;
|
||||
fin >> w;
|
||||
|
||||
graph->Insert(n1, n2, w);
|
||||
}
|
||||
|
||||
fin.close();
|
||||
cout << "success" << endl;
|
||||
}
|
||||
else if (cmd == "INSERT")
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
int w;
|
||||
|
||||
cin >> a;
|
||||
cin >> b;
|
||||
cin >> w;
|
||||
|
||||
try
|
||||
{
|
||||
if (graph->Insert(a, b, w))
|
||||
{
|
||||
mstModified = true;
|
||||
std::cout << "success" << std::endl;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
std::cout << "failure" << std::endl;
|
||||
}
|
||||
}
|
||||
catch (illegal_exception)
|
||||
{
|
||||
std::cout << "illegal argument" << std::endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "DELETE")
|
||||
{
|
||||
int a;
|
||||
cin >> a;
|
||||
|
||||
try
|
||||
{
|
||||
if (graph->Delete(a))
|
||||
{
|
||||
mstModified = true;
|
||||
std::cout << "success" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "failure" << std::endl;
|
||||
}
|
||||
}
|
||||
catch (illegal_exception)
|
||||
{
|
||||
std::cout << "illegal argument" << std::endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "PRINT")
|
||||
{
|
||||
int a;
|
||||
cin >> a;
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<std::tuple<int, int>> *out = graph->GetAdjacent(a);
|
||||
for (int i = 0; i < out->size(); i++)
|
||||
{
|
||||
std::cout << get<0>(out->at(i)) << " ";
|
||||
}
|
||||
|
||||
if (out->size() < 1)
|
||||
{
|
||||
std::cout << "failure";
|
||||
}
|
||||
std::cout << endl;
|
||||
}
|
||||
catch (illegal_exception)
|
||||
{
|
||||
std::cout << "illegal argument" << std::endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "MST")
|
||||
{
|
||||
// Prevent useless regeneration of MST.
|
||||
if (!mstModified)
|
||||
{
|
||||
if (prevOutput.size() < 1)
|
||||
std::cout << "failure";
|
||||
|
||||
for (int i = 0; i < prevOutput.size(); i++)
|
||||
{
|
||||
std::cout << std::get<0>(prevOutput[i]) << " " << std::get<1>(prevOutput[i]) << " " << std::get<2>(prevOutput[i]) << " ";
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::tuple<int, int, int>> out;
|
||||
out.reserve(graph->GetVertexCount());
|
||||
prevCost = graph->MST(&out);
|
||||
prevOutput = out;
|
||||
|
||||
for (int i = 0; i < out.size(); i++)
|
||||
{
|
||||
std::cout << std::get<0>(out[i]) << " " << std::get<1>(out[i]) << " " << std::get<2>(out[i]) << " ";
|
||||
}
|
||||
|
||||
if (out.size() < 1)
|
||||
std::cout << "failure";
|
||||
|
||||
std::cout << std::endl;
|
||||
mstModified = false;
|
||||
}
|
||||
}
|
||||
else if (cmd == "COST")
|
||||
{
|
||||
// Prevent useless regeneration of MST.
|
||||
if (!mstModified)
|
||||
{
|
||||
std::cout << "cost is " << prevCost << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::tuple<int, int, int>> out;
|
||||
out.reserve(graph->GetVertexCount());
|
||||
int cost = graph->MST(&out);
|
||||
prevOutput = out;
|
||||
prevCost = cost;
|
||||
|
||||
std::cout << "cost is " << cost << std::endl;
|
||||
mstModified = false;
|
||||
}
|
||||
}
|
||||
|
||||
else if (cmd == "END")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete graph;
|
||||
}
|
||||
10
P4/illegal_exception.h
Normal file
10
P4/illegal_exception.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef ILLEGAL_EXCEPTION_H
|
||||
#define ILLEGAL_EXCEPTION_H
|
||||
|
||||
#include <exception>
|
||||
|
||||
class illegal_exception : std::exception
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user