School Commit Init

This commit is contained in:
2024-08-31 12:07:21 +03:00
commit 0b130ee18c
2801 changed files with 4720552 additions and 0 deletions
@@ -0,0 +1,17 @@
#include <iostream>
#include "Matrix.h"
#include "ExtendedTest.h"
#include "ShortTest.h"
using namespace std;
int main() {
testAll();
testAllExtended();
cout << "Test End" << endl;
system("pause");
}
@@ -0,0 +1,166 @@
#include <assert.h>
#include "Matrix.h"
#include "ExtendedTest.h"
#include <iostream>
#include <exception>
using namespace std;
void testCreate() {
cout << "Test create" << endl;
Matrix m(10, 10);
assert(m.nrLines() == 10);
assert(m.nrColumns() == 10);
for (int i = 0; i < m.nrLines(); i++)
for (int j = 0; j < m.nrColumns(); j++)
assert(m.element(i, j) == NULL_TELEM);
}
void testModify() {
cout << "Test modify" << endl;
Matrix m(10, 10);
for (int j = 0; j < m.nrColumns(); j++)
m.modify(4, j, 3);
for (int i = 0; i < m.nrLines(); i++)
for (int j = 0; j < m.nrColumns(); j++)
if (i == 4)
assert(m.element(i, j) == 3);
else
assert(m.element(i, j) == NULL_TELEM);
}
void testQuantity() {
cout << "Test quantity" << endl;
Matrix m(200, 300);
for (int i = m.nrLines() / 2; i < m.nrLines(); i++) {
for (int j = 0; j <= m.nrColumns() / 2; j++)
{
int v1 = j;
int v2 = m.nrColumns() - v1 - 1;
if (i % 2 == 0 && v1 % 2 == 0)
m.modify(i, v1, i*v1);
else
if (v1 % 3 == 0)
m.modify(i, v1, i + v1);
if (i % 2 == 0 && v2 % 2 == 0)
m.modify(i, v2, i*v2);
else
if (v2 % 3 == 0)
m.modify(i, v2, i + v2);
}
}
for (int i = 0; i <= m.nrLines() / 2; i++) {
for (int j = 0; j <= m.nrColumns() / 2; j++)
{
int v1 = j;
int v2 = m.nrColumns() - v1 - 1;
if (i % 2 == 0 && v1 % 2 == 0)
m.modify(i, v1, i*v1);
else
if (v1 % 3 == 0)
m.modify(i, v1, i + v1);
if (i % 2 == 0 && v2 % 2 == 0)
m.modify(i, v2, i*v2);
else
if (v2 % 3 == 0)
m.modify(i, v2, i + v2);
}
}
for (int i = 0; i < m.nrLines(); i++)
for (int j = 0; j < m.nrColumns(); j++)
if (i % 2 == 0 && j % 2 == 0)
assert(m.element(i, j) == i * j);
else
if (j % 3 == 0)
assert(m.element(i, j) == i + j);
else assert(m.element(i, j) == NULL_TELEM);
}
void testExceptions() {
cout << "Test exceptions" << endl;
Matrix m(10, 10);
try {
m.element(-10, 0);
assert(false);
}
catch (exception&) {
assert(true);
}
try {
m.modify(12, 0, 1);
assert(false);
}
catch (exception&) {
assert(true);
}
try {
assert(m.nrLines());
}
catch (exception&) {
assert(false);
}
}
void testMix() {
cout << "Test mix" << endl;
int size = 2000;
Matrix m(size/2, size);
for (int i = 0; i < size/2; i++) {
for (int j = 0; j < size; j++) {
if (i == j) {
m.modify(i, j, 11);
}
else if (i == 100 * j) {
m.modify(i, j, 111);
}
else if ((i + j) % 1111 == 0) {
m.modify(i, j, 1111);
}
}
}
for (int i = 0; i < size/2; i++) {
for (int j = 0; j < size; j++) {
if (i == j) {
TElem old = m.modify(i, j, NULL_TELEM);
assert(old == 11);
}
else if (i == 100 * j) {
TElem old = m.modify(i, j, -111);
assert(old == 111);
}
else if ((i + j) % 1111 == 3) {
m.modify(i, j, 1);
}
}
}
for (int i = 0; i < size/2; i++) {
for (int j = 0; j < size; j++) {
TElem e = m.element(i, j);
if (i == j) {
assert(e == NULL_TELEM);
}
else if (i == 100 * j) {
assert(e == -111);
}
else if ((i + j) % 1111 == 3) {
assert(e == 1);
}
else if ((i + j) % 1111 == 0) {
assert(e == 1111);
}
else {
assert(e == NULL_TELEM);
}
}
}
}
void testAllExtended() {
testCreate();
testModify();
testQuantity();
testMix();
testExceptions();
}
@@ -0,0 +1,4 @@
#pragma once
#include "ExtendedTest.h"
void testAllExtended();
@@ -0,0 +1,81 @@
#include "Matrix.h"
#include <exception>
using namespace std;
Matrix::Matrix(int nrLines, int nrColumns) {
// Theta(1)
if (nrLines <= 0 || nrColumns <= 0) {
throw exception();
}
this->numberOfLines = nrLines;
this->numberOfColumns = nrColumns;
this->values = new TElem[nrLines * nrColumns];
this->lines = new int[nrLines * nrColumns];
this->columns = new int[nrColumns+1];
for (int i = 0; i < nrColumns+1; i++) {
this->columns[i] = 0;
}
}
int Matrix::nrLines() const {
// Theta(1)
return this->numberOfLines;
}
int Matrix::nrColumns() const {
// Theta(1)
return this->numberOfColumns;
}
TElem Matrix::element(int i, int j) const {
// Best: theta(1) | Worst: theta( nr of non-zero elements in the column) | Total: theta( nr of non-zero elements in the column)
if(i>=this->numberOfLines || j>=this->numberOfColumns || i<0 || j<0)
throw exception();
for(int k=0;k<this->columns[j+1]-this->columns[j];k++){
if(this->lines[k+this->columns[j]]==i)
return this->values[k+this->columns[j]];
}
return NULL_TELEM;
}
TElem Matrix::modify(int i, int j, TElem e) {
// Best: theta(1) | Worst: theta( nr of rows + nr of non zero values + nr of non zero values in the column) | Total: theta( nr of rows + nr of non zero values + nr of non zero values in the column)
if(i>=this->numberOfLines || j>=this->numberOfColumns || i<0 || j<0)
throw exception();
for(int k=0;k<this->columns[j+1]-this->columns[j];k++){
if(this->lines[k+this->columns[j]]==i){
swap(this->values[k+this->columns[j]],e);
return e;
}
}
for(int k=this->columns[this->numberOfColumns];k>this->columns[j];k--){
swap(this->lines[k],this->lines[k-1]);
swap(this->values[k],this->values[k-1]);
}
this->lines[this->columns[j]]=i;
this->values[this->columns[j]]=e;
for(int k=j+1;k<=this->numberOfColumns;k++)
this->columns[k]++;
return NULL_TELEM;
}
void Matrix::setMainDiagonal(TElem e) {
// Theta(min(nr of rows,nr of cols))
int length = this->numberOfLines;
if (this->numberOfColumns < this->numberOfLines) {
length = this->numberOfColumns;
}
for (int i = 0; i < length; i++) {
this->modify(i, i, e);
}
}
@@ -0,0 +1,39 @@
#pragma once
//DO NOT CHANGE THIS PART
typedef int TElem;
#define NULL_TELEM 0
class Matrix {
private:
//TODO - Representation
TElem* values;
int* lines;
int* columns;
int numberOfLines;
int numberOfColumns;
public:
//constructor
Matrix(int nrLines, int nrCols);
//returns the number of lines
int nrLines() const;
//returns the number of columns
int nrColumns() const;
//returns the element from line i and column j (indexing starts from 0)
//throws exception if (i,j) is not a valid position in the Matrix
TElem element(int i, int j) const;
//modifies the value from line i and column j
//returns the previous value from the position
//throws exception if (i,j) is not a valid position in the Matrix
TElem modify(int i, int j, TElem e);
void setMainDiagonal(TElem e);
};
@@ -0,0 +1,15 @@
#include <assert.h>
#include "Matrix.h"
using namespace std;
void testAll() {
Matrix m(4, 4);
assert(m.nrLines() == 4);
assert(m.nrColumns() == 4);
m.modify(1, 1, 5);
assert(m.element(1, 1) == 5);
TElem old = m.modify(1, 1, 6);
assert(m.element(1, 2) == NULL_TELEM);
assert(old == 5);
}
@@ -0,0 +1,3 @@
#pragma once
void testAll();
@@ -0,0 +1,19 @@
#include "ExtendedTest.h"
#include "ShortTest.h"
#include "SortedMap.h"
#include <iostream>
using namespace std;
int main() {
testAll();
testAllExtended();
cout << "That's all!" << endl;
system("pause");
return 0;
}
Binary file not shown.
@@ -0,0 +1,341 @@
#include <exception>
#include <assert.h>
#include <algorithm>
#include <vector>
#include <iostream>
#include "SortedMap.h"
#include "SMIterator.h"
#include "ExtendedTest.h"
using namespace std;
bool increasing(TKey c1, TKey c2) {
if (c1 <= c2) {
return true;
} else {
return false;
}
}
bool decreasing(TKey c1, TKey c2) {
if (c1 >= c2) {
return true;
} else {
return false;
}
}
void testIteratorSteps(SortedMap& m, Relation r) {
SMIterator li = m.iterator();
TElem elem = NULL_TPAIR;
int count = 0;
if (li.valid()) {
elem = li.getCurrent();
count++;
li.next();
}
while (li.valid()) {
TElem elem2 = li.getCurrent();
assert(r(elem.first, elem2.first));
elem = elem2;
count++;
li.next();
}
assert(count == m.size());
}
void testCreate() {
cout << "Test create" << endl;
SortedMap sm(increasing);
assert(sm.size() == 0);
assert(sm.isEmpty());
SMIterator it = sm.iterator();
it.first();
assert(!it.valid());
try {
it.next();
assert(false);
}
catch (exception&) {
assert(true);
}
try {
it.getCurrent();
assert(false);
}
catch (exception&) {
assert(true);
}
for (int i = 0; i < 10; i++) {
assert(sm.search(i) == NULL_TVALUE);
}
for (int i = -10; i < 10; i++) {
assert(sm.remove(i) == NULL_TVALUE);
}
}
void testSearch(Relation r) {
cout << "Test search" << endl;
SortedMap sm(r);
int cMin = 0;
int cMax = 10;
try {
for (int i = cMin; i <= cMax; i++) {
sm.add(i, i + 1);
}
assert(true);
} catch (exception&) {
assert(false);
}
int intervalDim = 10;
for (int i = cMin; i <= cMax; i++) {
assert(sm.search(i) == i + 1);
}
testIteratorSteps(sm, r);
for (int i = cMin - intervalDim; i < cMin; i++) {
assert(sm.search(i) == NULL_TVALUE);
}
for (int i = cMax + 1; i < cMax + intervalDim; i++) {
assert(sm.search(i) == NULL_TVALUE);
}
}
void testSearch() {
testSearch(increasing);
testSearch(decreasing);
}
vector<int> keysInRandomOrder(int cMin, int cMax) {
vector<int> keys;
for (int c = cMin; c <= cMax; c++) {
keys.push_back(c);
}
int n = keys.size();
for (int i = 0; i < n - 1; i++) {
int j = i + rand() % (n - i);
swap(keys[i], keys[j]);
}
return keys;
}
void populateSMEmpty(SortedMap& sm, int cMin, int cMax) {
vector<int> keys = keysInRandomOrder(cMin, cMax);
int n = keys.size();
for (int i = 0; i < n; i++) {
assert(sm.add(keys[i], keys[i]) == NULL_TVALUE);
}
}
void rePopulateSMShift(SortedMap& sm, int cMin, int cMax, int shift) {
vector<int> keys = keysInRandomOrder(cMin, cMax);
int n = keys.size();
for (int i = 0; i < n; i++) {
assert(sm.add(keys[i], keys[i] - shift) == keys[i]);
}
}
void populateSMShift(SortedMap& sm, int cMin, int cMax, int shift) {
vector<int> keys = keysInRandomOrder(cMin, cMax);
int n = keys.size();
for (int i = 0; i < n; i++) {
sm.add(keys[i], keys[i] - shift);
}
}
void testAddAndSearch(Relation r) {
cout << "Test add and search" << endl;
SortedMap sm(r);
int cMin = 100;
int cMax = 200;
populateSMEmpty(sm, cMin, cMax);
testIteratorSteps(sm, r);
for (int c = cMin; c <= cMax; c++) {
assert(sm.search(c) == c);
}
assert(sm.size() == (cMax - cMin + 1));
rePopulateSMShift(sm, cMin, cMax, 1);
assert(sm.size() == (cMax - cMin + 1));
testIteratorSteps(sm, r);
populateSMShift(sm, 2 * cMax, 3 * cMax, 2 * cMax - cMin);
for (int c = 2 * cMax; c <= 3 * cMax; c++) {
assert(sm.search(c) == c - 2 * cMax + cMin);
}
testIteratorSteps(sm, r);
assert(sm.size() == (cMax - cMin + 1) + (cMax + 1));
SMIterator it = sm.iterator();
it.first();
if (it.valid()) {
TKey cPrec = it.getCurrent().first;
assert(sm.search(cPrec) != NULL_TVALUE);
it.next();
while (it.valid()) {
TKey c = it.getCurrent().first;
assert(r(cPrec, c));
assert(sm.search(c) != NULL_TVALUE);
cPrec = c;
it.next();
}
}
}
void testAdd() {
testAddAndSearch(increasing);
testAddAndSearch(decreasing);
}
void testRemoveAndSearch(Relation r) {
cout << "Test remove and search" << endl;
SortedMap sm(r);
int cMin = 10;
int cMax = 20;
populateSMEmpty(sm, cMin, cMax);
testIteratorSteps(sm, r);
for (int c = cMax + 1; c <= 2 * cMax; c++) {
assert(sm.remove(c) == NULL_TVALUE);
testIteratorSteps(sm, r);
}
int dim = cMax - cMin + 1;
assert(sm.size() == dim);
for (int c = cMin; c <= cMax; c++) {
assert(sm.remove(c) == c);
assert(sm.search(c) == NULL_TVALUE);
SMIterator it = sm.iterator();
it.first();
if (it.valid()) {
TKey cPrec = it.getCurrent().first;
it.next();
while (it.valid()) {
TKey c = it.getCurrent().first;
assert(r(cPrec, c));
cPrec = c;
it.next();
}
}
dim--;
assert(sm.size() == dim);
}
for (int c = cMin; c <= cMax; c++) {
assert(sm.remove(c) == NULL_TVALUE);
}
assert(sm.isEmpty());
assert(sm.size() == 0);
}
void testRemove() {
testRemoveAndSearch(increasing);
testRemoveAndSearch(decreasing);
}
void testIterator(Relation r) {
cout << "Test iterator" << endl;
SortedMap sm(r);
SMIterator it = sm.iterator();
assert(!it.valid());
it.first();
assert(!it.valid());
int cMin = 100;
int cMax = 300;
vector<int> keys = keysInRandomOrder(cMin, cMax);
int n = keys.size();
for (int i = 0; i < n; i++) {
assert(sm.add(keys[i], keys[n - i - 1]) == NULL_TVALUE);
}
SMIterator itSM = sm.iterator();
assert(itSM.valid());
itSM.first();
assert(itSM.valid());
TKey cPrec = itSM.getCurrent().first;
for (int i=1; i<100; i++){
assert(cPrec == itSM.getCurrent().first);
}
itSM.next();
while (itSM.valid()) {
TKey c = itSM.getCurrent().first;
assert(cMin <= c && c <= cMax);
assert(sm.search(c) != NULL_TVALUE);
assert(r(cPrec, c));
cPrec = c;
itSM.next();
}
}
void testQuantity(){
cout << "Test quantity" << endl;
SortedMap sm(increasing);
int cMin = -3000;
int cMax = 3000;
vector<int> keys = keysInRandomOrder(cMin, cMax);
populateSMEmpty(sm, cMin, cMax);
for (int c = cMin; c <= cMax; c++){
assert(sm.search(c) == c);
}
testIteratorSteps(sm, increasing);
assert(sm.size() == cMax - cMin + 1);
SMIterator it = sm.iterator();
assert(it.valid());
it.first();
assert(it.valid());
for (int i = 0; i < sm.size(); i++) {
it.next();
}
assert(!it.valid());
it.first();
while (it.valid()){
TKey c = it.getCurrent().first;
assert(sm.search(c) == c);
TValue v = it.getCurrent().second;
assert(c == v);
it.next();
}
assert(!it.valid());
for (int c = cMin-100; c <= cMax+100; c++){
sm.remove(c);
assert(sm.search(c) == NULL_TVALUE);
testIteratorSteps(sm, increasing);
}
assert(sm.size() == 0);
assert(sm.isEmpty());
}
void testIterator() {
testIterator(increasing);
testIterator(decreasing);
}
void testExtra(){
cout << "Test extra" << endl;
SortedMap sm(increasing);
sm.add(1, 1);
sm.add(2, 2);
sm.add(3, 3);
sm.add(4, 3);
vector<TValue> v = sm.valueBag();
assert(v.size() == 3);
assert(v[0] == 1);
assert(v[1] == 2);
assert(v[2] == 3);
}
void testAllExtended() {
testCreate();
testAdd();
testSearch();
testRemove();
testIterator();
testQuantity();
testExtra();
}
@@ -0,0 +1,4 @@
#pragma once
void testAllExtended();
@@ -0,0 +1,39 @@
#include "SMIterator.h"
#include "SortedMap.h"
#include <exception>
using namespace std;
SMIterator::SMIterator(const SortedMap& m) : map(m){
//Complexity: O(1)
this->current = this->map.head;
}
void SMIterator::first(){
//Complexity: O(1)
this->current = this->map.head;
}
void SMIterator::next(){
//Complexity: O(1)
if (this->current == nullptr)
throw exception();
this->current = this->current->next;
}
bool SMIterator::valid() const{
//Complexity: O(1)
if(this->current == nullptr)
return false;
return true;
}
TElem SMIterator::getCurrent() const{
//Complexity: O(1)
if(this->current==nullptr)
throw exception();
return this->current->element;
}
@@ -0,0 +1,20 @@
#pragma once
#include "SortedMap.h"
//DO NOT CHANGE THIS PART
class SMIterator{
friend class SortedMap;
private:
const SortedMap& map;
SMIterator(const SortedMap& mapionar);
//TODO - Representation
Node* current;
public:
void first();
void next();
bool valid() const;
TElem getCurrent() const;
};
@@ -0,0 +1,39 @@
#include <assert.h>
#include "SortedMap.h"
#include "SMIterator.h"
#include "ShortTest.h"
#include <exception>
using namespace std;
bool relatie1(TKey cheie1, TKey cheie2) {
if (cheie1 <= cheie2) {
return true;
}
else {
return false;
}
}
void testAll(){
SortedMap sm(relatie1);
assert(sm.size() == 0);
assert(sm.isEmpty());
sm.add(1,2);
assert(sm.size() == 1);
assert(!sm.isEmpty());
assert(sm.search(1)!=NULL_TVALUE);
TValue v =sm.add(1,3);
assert(v == 2);
assert(sm.search(1) == 3);
SMIterator it = sm.iterator();
it.first();
while (it.valid()){
TElem e = it.getCurrent();
assert(e.second != NULL_TVALUE);
it.next();
}
assert(sm.remove(1) == 3);
assert(sm.isEmpty());
}
@@ -0,0 +1,3 @@
#pragma once
void testAll();
@@ -0,0 +1,130 @@
#include "SMIterator.h"
#include "SortedMap.h"
#include <exception>
#include <algorithm>
using namespace std;
SortedMap::SortedMap(Relation r) {
//Complexity: O(1)
this->relation = r;
this->head = nullptr;
this->length = 0;
}
TValue SortedMap::add(TKey k, TValue v) {
//Complexity: O(n) - average/worst O(1) - best
if (this->head == nullptr){
this->head = new Node(pair<TKey, TValue>(k, v));
this->length++;
return NULL_TVALUE;
}
if (this->head->element.first == k){
TValue value = this->head->element.second;
this->head->element.second = v;
return value;
}
if(this->relation(k, this->head->element.first)){
Node* new_node = new Node(pair<TKey, TValue>(k, v));
new_node->next = this->head;
this->head = new_node;
this->length++;
return NULL_TVALUE;
}
Node* previous_node = this->head;
Node* current_node = this->head->next;
for(int i = 0; i < this->length-1; i++){
if (current_node->element.first == k){
TValue value = current_node->element.second;
current_node->element.second = v;
return value;
}
if (this->relation(k, current_node->element.first)){
Node* new_node = new Node(pair<TKey, TValue>(k, v));
new_node->next = current_node;
previous_node->next = new_node;
this->length++;
return NULL_TVALUE;
}
previous_node = current_node;
current_node = current_node->next;
}
previous_node->next = new Node(pair<TKey, TValue>(k, v));
this->length++;
return NULL_TVALUE;
}
TValue SortedMap::search(TKey k) const {
//Complexity: O(n) - average/worst O(1) - best
Node* current_node = this->head;
for(int i = 0; i< this->length; i++){
if (current_node->element.first == k)
return current_node->element.second;
current_node = current_node->next;
}
return NULL_TVALUE;
}
TValue SortedMap::remove(TKey k) {
//Complexity: O(n) - average/worst O(1) - best
if(this->head!=nullptr && this->head->element.first == k){
Node* new_head = this->head->next;
TValue value = this->head->element.second;
delete this->head;
this->head = new_head;
this->length--;
return value;
}
Node* current_node = this->head;
for(int i = 1; i< this->length; i++){
if (current_node->next->element.first == k){
Node* removed_node = current_node->next;
TValue value = removed_node->element.second;
current_node->next = current_node->next->next;
delete removed_node;
this->length--;
return value;
}
current_node = current_node->next;
}
return NULL_TVALUE;
}
int SortedMap::size() const {
//Complexity: O(1)
return this->length;
}
bool SortedMap::isEmpty() const {
//Complexity: O(1)
if (this->length == 0)
return true;
return false;
}
SMIterator SortedMap::iterator() const {
//Complexity: O(1)
return SMIterator(*this);
}
SortedMap::~SortedMap() {
//Complexity: O(n)
Node* current_node = this->head;
for(int i = 0; i < this->length; i++){
Node* next_node = current_node->next;
delete current_node;
current_node = next_node;
}
}
std::vector<TValue> SortedMap::valueBag() {
//Complexity: O(n*m) - average/worst O(n) - best
vector<TValue> values;
Node* current_node = this->head;
for(int i = 0; i < this->length; i++){
if (find(values.begin(), values.end(), current_node->element.second) == values.end())
values.push_back(current_node->element.second);
current_node = current_node->next;
}
return values;
}
@@ -0,0 +1,70 @@
#pragma once
//DO NOT INCLUDE SORTEDMAPITERATOR
#include <vector>
//DO NOT CHANGE THIS PART
typedef int TKey;
typedef int TValue;
#include <utility>
typedef std::pair<TKey, TValue> TElem;
#define NULL_TVALUE -111111
#define NULL_TPAIR pair<TKey, TValue>(-111111, -111111);
class SMIterator;
typedef bool(*Relation)(TKey, TKey);
class Node {
public:
TElem element;
Node* next;
Node(TElem e) {
element = e;
next = nullptr;
}
Node(TElem e, Node* n) {
element = e;
next = n;
}
bool operator==(Node* n) {
return this->element.first == n->element.first;
}
};
class SortedMap {
friend class SMIterator;
private:
//TODO - Representation
Node* head;
Relation relation;
int length;
public:
// implicit constructor
SortedMap(Relation r);
// adds a pair (key,value) to the map
//if the key already exists in the map, then the value associated to the key is replaced by the new value and the old value is returned
//if the key SMes not exist, a new pair is added and the value null is returned
TValue add(TKey c, TValue v);
//searches for the key and returns the value associated with the key if the map contains the key or null: NULL_TVALUE otherwise
TValue search(TKey c) const;
//removes a key from the map and returns the value associated with the key if the key existed ot null: NULL_TVALUE otherwise
TValue remove(TKey c);
//returns the number of pairs (key,value) from the map
int size() const;
//checks whether the map is empty or not
bool isEmpty() const;
// return the iterator for the map
// the iterator will return the keys following the order given by the relation
SMIterator iterator() const;
// destructor
~SortedMap();
std::vector<TValue> valueBag();
};
@@ -0,0 +1,11 @@
#include <iostream>
#include "ShortTest.h"
#include "ExtendedTest.h"
int main(){
testAll();
testAllExtended();
std::cout<<"Finished IL Tests!"<<std::endl;
system("pause");
}
@@ -0,0 +1,387 @@
#include "ExtendedTest.h"
#include <assert.h>
#include <exception>
#include <cstdlib>
#include <vector>
#include <iostream>
#include "ListIterator.h"
#include "SortedIndexedList.h"
using namespace std;
//order relation - ascending
bool asc(TComp c1, TComp c2) {
if (c1 <= c2) {
return true;
} else {
return false;
}
}
//order relation - descending
bool desc(TComp c1, TComp c2) {
if (c1 >= c2) {
return true;
} else {
return false;
}
}
void testIteratorSteps(SortedIndexedList& list, Relation r) {
int count = 0;
ListIterator li = list.iterator();
TComp prev = li.getCurrent();
if (li.valid()) {
count++;
li.next();
}
while (li.valid()) {
TComp current = li.getCurrent();
assert(r(prev, current));
count++;
li.next();
prev = current;
}
assert(count == list.size());
}
void testCreate() {
cout << "Test create" << endl;
SortedIndexedList list = SortedIndexedList(asc);
assert(list.size() == 0);
assert(list.isEmpty());
ListIterator it = list.iterator();
assert(!it.valid());
it.first();
for (int i = 0; i < 10; i++) {
assert(!it.valid());
assert(list.search(i) == -1);
try {
assert(list.getElement(i));
assert(false);
} catch (exception&) {
assert(true);
}
try {
assert(list.remove(i));
assert(false);
} catch (exception&) {
assert(true);
}
try {
it.next();
assert(false);
}
catch (exception&) {
assert(true);
}
}
}
//generate a vector with values between cMin and cMax so that
//1) no value that is >=cMin and <=cMax which is a multiple of s is not included
//2) values v, v>=cMin and v<=cMax which are a multiple of m (but not of s) are included c/m + 1 times
//3) values >=cMin and <=cMax are in random order
vector<int> random(int cMin, int cMax, int s, int m) {
vector<int> v;
for (int c = cMin; c <= cMax; c++) {
if (c % s != 0) {
v.push_back(c);
if (c % m == 0) {
for (int j = 0; j < c / m; j++) {
v.push_back(c);
}
}
}
}
int n = v.size();
for (int i = 0; i < n - 1; i++) {
int j = i + rand() % (n - i);
swap(v[i], v[j]);
}
return v;
}
//generate a vector containing values >=cMin and <=cMax, each included one time, in random order
vector<int> random(int cMin, int cMax) {
vector<int> v;
for (int c = cMin; c <= cMax; c++) {
v.push_back(c);
}
int n = v.size();
for (int i = 0; i < n - 1; i++) {
int j = i + rand() % (n - i);
swap(v[i], v[j]);
}
return v;
}
//populate the sorted list with values >=cMin and <=cMax a.i.:
//1) no value that is >=cMin and <=cMax which is a multiple of s is not included
//2) values v, v>=cMin and v<=cMax which are a multiple of m (but not of s) are included c/m + 1 times
//3) values >=cMin and <=cMax are in random order
int populate(SortedIndexedList& list, int cMin, int cMax, int s, int m) {
vector<int> v = random(cMin, cMax, s, m);
int n = v.size();
for (int i = 0; i < n; i++) {
list.add(v[i]);
}
return n;
}
//populate the sorted list with values >=cMin and <=cMax, each included one time, in random order
void populate(SortedIndexedList& list, int cMin, int cMax) {
vector<int> v = random(cMin, cMax);
int n = v.size();
for (int i = 0; i < n; i++) {
list.add(v[i]);
}
}
void testAddAndSearch(Relation r) {
cout << "Test add and search" << endl;
SortedIndexedList list = SortedIndexedList(r);
int vMin = 10;
int vMax = 30;
int s = 5;
int m = 3;
int n = populate(list, vMin, vMax, s, m);
assert(!list.isEmpty());
assert(list.size() == n);
//we can't find values outside the interval or on invalid positions
int d = 30;
for (int i = 1; i <= d; i++) {
assert(list.search(vMin - i) == -1);
assert(list.search(vMax + i) == -1);
try{
list.getElement(n-1+i);
list.getElement(-d);
assert(false);
} catch (exception&) {
assert(true);
}
}
//check the relation order
ListIterator it = list.iterator();
it.first();
assert(it.valid());
TComp prev = it.getCurrent();
it.next();
while (it.valid()) {
TComp current = it.getCurrent();
assert(r(prev, current));
prev = current;
it.next();
}
testIteratorSteps(list, r);
//check if added values can be found
for (int v = vMin; v <= vMax; v++) {
int p = list.search(v);
//we can't find values which are a multiple of s
assert((p != -1) == (v % s != 0));
//values which are a multiple of m can be found exactly v/m+1 times
if (p != -1 && v%m == 0){
for (int i=0; i<=v/m; i++){
try{
assert(list.remove(p) == v);
} catch (exception&) {
assert(false);
}
}
assert(list.search(v) == -1);
}
}
}
void testDeleteSearch(Relation r) {
cout << "Test delete and search" << endl;
SortedIndexedList list = SortedIndexedList(r);
int vMin = 0;
int vMax = 100;
populate(list, vMin, vMax);
int d = 30;
for (int i = 1; i <= d; i++) {
try {
list.remove(list.search(vMax + i));
assert(false);
} catch (exception&) {
assert(true);
}
}
assert(!list.isEmpty());
assert(list.size() == vMax - vMin + 1);
ListIterator it1 = list.iterator();
assert(it1.valid());
it1.first();
assert(it1.valid());
TComp deleted = NULL_TCOMP;
testIteratorSteps(list, r);
try {
deleted = list.remove(list.search(it1.getCurrent()));
assert(list.size() == vMax - vMin);
it1.first();
TComp newFirst = it1.getCurrent();
assert(newFirst != deleted);
assert(r(deleted, newFirst));
it1.first();
ListIterator it2 = list.iterator();
assert(it2.valid());
it2.first();
assert(it2.valid());
assert(it1.getCurrent() == newFirst && it2.getCurrent() == newFirst);
} catch (exception&) {
assert(false);
}
//delete values in random order while checking the relation order
vector<int> vs = random(vMin, vMax);
int n = vs.size();
for (int i = 0; i < n; i++) {
testIteratorSteps(list, r);
int v = vs[i];
try {
int it1 = list.search(v);
TComp deletedCurrent = list.remove(it1);
assert(deletedCurrent != deleted);
assert(deletedCurrent == v);
assert(list.search(v) == -1);
if (!list.isEmpty()) {
ListIterator it2 = list.iterator();
it2.first();
assert(it2.valid());
TComp prev = it2.getCurrent();
while (it2.valid()) {
TComp current = list.getElement(list.search(it2.getCurrent()));
assert(r(prev, current));
assert(!r(deletedCurrent, current) || !r(current, deletedCurrent));
prev = current;
it2.next();
}
}
} catch (exception&) {
assert(v == deleted);
}
}
assert(list.isEmpty());
assert(list.size() == 0);
}
void testDeleteSearch() {
testDeleteSearch(asc);
testDeleteSearch(desc);
}
void testAddAndSearch() {
testAddAndSearch(asc);
testAddAndSearch(desc);
}
void testQuantity(){
cout << "Test quantity" << endl;
SortedIndexedList list = SortedIndexedList(asc);
int vMin = 3000;
int vMax = 6000;
vector<int> values = random(vMin, vMax);
int n = values.size();
for (int i = 0; i < n; i++){
list.add(values[i]);
}
assert(list.size() == vMax - vMin + 1);
for (int v = vMin; v <= vMax; v++){
assert(list.search(v)>= 0 && list.search(v) < list.size());
assert(list.getElement(list.search(v)) == v);
}
ListIterator it = list.iterator();
it.first();
assert(it.valid());
TComp firstElement = it.getCurrent();
it.first();
assert(it.valid());
assert(it.getCurrent() == firstElement);
for (int i = 0; i < list.size(); i++) {
it.next();
}
assert(!it.valid());
it.first();
while (it.valid()){
TComp v = it.getCurrent();
assert(vMin <= v && v<=vMax);
it.next();
}
assert(!it.valid());
int d = 100;
//consider the interval [vMin-d, vMax+d]
for (int v = vMin-d; v <= vMax+d; v++){
//check that only values from the interval [vMin, vMax] are included in the list
assert((list.search(v) != -1) == (vMin <= v && v <= vMax));
try{
assert(list.remove(list.search(v)));
assert(vMin <= v && v <= vMax);
} catch (exception&) {
assert(vMin > v || v > vMax);
}
}
assert(list.size() == 0);
assert(list.isEmpty());
}
void testPrevious(){
cout << "Test previous" << endl;
SortedIndexedList list = SortedIndexedList(asc);
list.add(1);
list.add(3);
list.add(7);
list.add(10);
list.add(12);
ListIterator it = list.iterator();
it.last();
assert(it.valid());
assert(it.getCurrent() == 12);
it.previous();
assert(it.valid());
assert(it.getCurrent() == 10);
it.previous();
assert(it.valid());
assert(it.getCurrent() == 7);
it.previous();
assert(it.valid());
assert(it.getCurrent() == 3);
it.previous();
assert(it.valid());
assert(it.getCurrent() == 1);
it.previous();
assert(!it.valid());
}
void testAllExtended() {
testCreate();
testAddAndSearch();
testDeleteSearch();
testQuantity();
testPrevious();
}
@@ -0,0 +1,3 @@
#pragma once
void testAllExtended();
@@ -0,0 +1,49 @@
#include "ListIterator.h"
#include "SortedIndexedList.h"
#include <iostream>
using namespace std;
ListIterator::ListIterator(const SortedIndexedList& list) : list(list) {
// O(1)
this->_current = list._head;
}
void ListIterator::first(){
// O(1)
this->_current = this->list._head;
}
void ListIterator::next(){
// O(1)
if(!this->valid())
throw exception();
this->_current = this->list._next[this->_current];
}
bool ListIterator::valid() const{
// O(1)
if(this->_current != -1)
return true;
return false;
}
TComp ListIterator::getCurrent() const{
// O(1)
if(this->valid())
return this->list._elements[this->_current];
return NULL_TCOMP;
}
void ListIterator::previous(){
// O(1)
if(!this->valid())
throw exception();
this->_current = this->list._prev[this->_current];
}
void ListIterator::last(){
// O(1)
this->_current = this->list._tail;
}
@@ -0,0 +1,24 @@
#pragma once
#include "SortedIndexedList.h"
//DO NOT CHANGE THIS PART
class ListIterator{
friend class SortedIndexedList;
private:
const SortedIndexedList& list;
ListIterator(const SortedIndexedList& list);
//TODO - Representation
int _current;
public:
void first();
void last();
void next();
bool valid() const;
TComp getCurrent() const;
void previous();
};
@@ -0,0 +1,37 @@
#include <assert.h>
#include "ListIterator.h"
#include "SortedIndexedList.h"
using namespace std;
bool relation1(TComp e1, TComp e2) {
if (e1 <= e2) {
return true;
}
else {
return false;
}
}
void testAll(){
SortedIndexedList list = SortedIndexedList(relation1);
assert(list.size() == 0);
assert(list.isEmpty());
list.add(1);
assert(list.size() == 1);
assert(!list.isEmpty());
ListIterator iterator = list.iterator();
assert(iterator.valid());
iterator.first();
assert(iterator.getCurrent() == 1);
iterator.next();
assert(!iterator.valid());
iterator.first();
assert(iterator.valid());
assert(list.search(1) == 0);
assert(list.remove(0) == 1);
assert(list.size() == 0);
assert(list.isEmpty());
}
@@ -0,0 +1,3 @@
#pragma once
void testAll();
@@ -0,0 +1,149 @@
#include "ListIterator.h"
#include "SortedIndexedList.h"
#include <iostream>
using namespace std;
#include <exception>
SortedIndexedList::SortedIndexedList(Relation r) {
// O(1)
this->_relation = r;
this->_capacity = 10;
this->_length = 0;
this->_elements = new TComp[this->_capacity];
this->_next = new int[this->_capacity];
this->_prev = new int[this->_capacity];
for(int i = 0; i < this->_capacity; i++){
this->_elements[i] = NULL_TCOMP;
this->_next[i] = -1;
this->_prev[i] = -1;
}
this->_head = -1;
this->_tail = -1;
this->_firstEmpty = 0;
}
int SortedIndexedList::size() const {
//O(1)
return this->_length;
}
bool SortedIndexedList::isEmpty() const {
//O(1)
return this->_length == 0;
}
TComp SortedIndexedList::getElement(int i) const{
//O(i) - average case | O(i) - worst case | O(i) - best case
if(i < 0 || i >= this->_length)
throw exception();
int current = this->_head;
while(i != 0){
i--;
current = this->_next[current];
}
return this->_elements[current];
}
TComp SortedIndexedList::remove(int i) {
// O(i) - average case | O(i) - worst case | O(i) - best case
if(i < 0 || i >= this->_length)
throw exception();
int current = this->_head;
while(i != 0){
i--;
current = this->_next[current];
}
TComp removed = this->_elements[current];
if(this->_head == current)
this->_head = this->_next[current];
else
this->_next[this->_prev[current]] = this->_next[current];
if(this->_tail == current)
this->_tail = this->_prev[current];
else
this->_prev[this->_next[current]] = this->_prev[current];
this->_elements[current] = NULL_TCOMP;
this->_next[current] = -1;
this->_prev[current] = -1;
this->_length--;
if(this->_firstEmpty > current)
this->_firstEmpty = current;
return removed;
}
int SortedIndexedList::search(TComp e) const {
//O(n) - average case | O(n) - worst case | O(1) - best case
int current = this->_head;
int i = 0;
while(current != -1){
if(this->_elements[current] == e)
return i;
current = this->_next[current];
i++;
}
return -1;
}
void SortedIndexedList::add(TComp e) {
// O(n) - average case | O(n) - worst case | O(1) - best case
if(this->_length == this->_capacity)
this->resize();
int current = this->_head;
int prev = -1;
while(current != -1 && this->_relation(this->_elements[current], e)){
prev = current;
current = this->_next[current];
}
this->_elements[this->_firstEmpty] = e;
this->_next[this->_firstEmpty] = current;
this->_prev[this->_firstEmpty] = prev;
if(prev == -1)
this->_head = this->_firstEmpty;
else
this->_next[prev] = this->_firstEmpty;
if(current == -1)
this->_tail = this->_firstEmpty;
else
this->_prev[current] = this->_firstEmpty;
this->_length++;
while(this->_firstEmpty < this->_capacity && this->_elements[this->_firstEmpty] != NULL_TCOMP)
this->_firstEmpty++;
}
ListIterator SortedIndexedList::iterator(){
//O(1)
return ListIterator(*this);
}
//destructor
SortedIndexedList::~SortedIndexedList() {
//O(1)
delete[] this->_elements;
delete[] this->_next;
delete[] this->_prev;
}
void SortedIndexedList::resize(){
//O(n)
this->_capacity *= 2;
TComp* newElements = new TComp[this->_capacity];
int* newNext = new int[this->_capacity];
int* newPrev = new int[this->_capacity];
for(int i = 0; i < this->_capacity; i++){
newElements[i] = NULL_TCOMP;
newNext[i] = -1;
newPrev[i] = -1;
}
for(int i = 0; i < this->_length; i++){
newElements[i] = this->_elements[i];
newNext[i] = this->_next[i];
newPrev[i] = this->_prev[i];
}
delete[] this->_elements;
delete[] this->_next;
delete[] this->_prev;
this->_elements = newElements;
this->_next = newNext;
this->_prev = newPrev;
}
@@ -0,0 +1,57 @@
#pragma once
//DO NOT INCLUDE LISTITERATOR
//DO NOT CHANGE THIS PART
class ListIterator;
typedef int TComp;
typedef bool (*Relation)(TComp, TComp);
#define NULL_TCOMP -11111
class SortedIndexedList {
private:
friend class ListIterator;
private:
//TODO - Representation
Relation _relation;
int _capacity;
int _length;
TComp* _elements;
int* _next;
int* _prev;
int _head;
int _tail;
int _firstEmpty;
void resize();
public:
// constructor
SortedIndexedList(Relation r);
// returns the size of the list
int size() const;
//checks if the list is empty
bool isEmpty() const;
// returns an element from a position
//throws exception if the position is not valid
TComp getElement(int pos) const;
// adds an element in the sortedList (to the corresponding position)
void add(TComp e);
// removes an element from a given position
//returns the removed element
//throws an exception if the position is not valid
TComp remove(int pos);
// searches for an element and returns the first position where the element appears or -1 if the element is not in the list
int search(TComp e) const;
// returns an iterator set to the first element of the list or invalid if the list is empty
ListIterator iterator();
//destructor
~SortedIndexedList();
};
@@ -0,0 +1,18 @@
#include "ExtendedTest.h"
#include "ShortTest.h"
#include "Map.h"
#include <iostream>
using namespace std;
int main() {
testAll();
testAllExtended();
cout << "That's all!" << endl;
system("pause");
return 0;
}
@@ -0,0 +1,291 @@
#include "ExtendedTest.h"
#include "Map.h"
#include "MapIterator.h"
#include <assert.h>
#include <iostream>
using namespace std;
void testIteratorSteps(Map& m) {
MapIterator mi = m.iterator();
int count = 0;
while (mi.valid()) {
count++;
mi.next();
}
assert(count == m.size());
}
void testCreate() {
cout << "Test create" << endl;
Map m;
assert(m.size() == 0);
assert(m.isEmpty() == true);
for (int i = -10; i < 10; i++) {
assert(m.search(i) == NULL_TVALUE);
}
for (int i = -10; i < 10; i++) {
assert(m.search(i) == NULL_TVALUE);
}
MapIterator it = m.iterator();
assert(it.valid() == false);
try {
it.next();
assert(false);
}
catch (exception&) {
assert(true);
}
try {
it.getCurrent();
assert(false);
}
catch (exception&) {
assert(true);
}
}
void testAdd() {
cout << "Test add" << endl;
Map m;
for (int i = 0; i < 10; i++) {
assert(m.add(i, i) == NULL_TVALUE);
}
assert(m.isEmpty() == false);
assert(m.size() == 10);
for (int i = -10; i < 0; i++) {
assert(m.add(i, i) == NULL_TVALUE);
}
for (int i = 0; i < 10; i++) {
assert(m.add(i, i) == i);
}
for (int i = 10; i < 20; i++) {
assert(m.add(i, i) == NULL_TVALUE);
}
assert(m.isEmpty() == false);
assert(m.size() == 30);
for (int i = -100; i < 100; i++) {
m.add(i, i);
}
assert(m.isEmpty() == false);
assert(m.size() == 200);
for (int i = -200; i < 200; i++) {
if (i < -100) {
assert(m.search(i) == NULL_TVALUE);
}
else if (i < 0) {
assert(m.search(i) == i);
}
else if (i < 100) {
assert(m.search(i) == i);
}
else {
assert(m.search(i) == NULL_TVALUE);
}
}
for (int i = 10000; i > -10000; i--) {
m.add(i, i);
}
testIteratorSteps(m);
assert(m.size() == 20000);
}
void testRemove() {
cout << "Test remove" << endl;
Map m;
for (int i = -100; i < 100; i++) {
assert(m.remove(i) == NULL_TVALUE);
}
assert(m.size() == 0);
for (int i = -100; i < 100; i = i + 2) {
assert(m.add(i, i) == NULL_TVALUE);
}
for (int i = -100; i < 100; i++) {
if (i % 2 == 0) {
assert(m.remove(i) == i);
}
else {
assert(m.remove(i) == NULL_TVALUE);
}
}
assert(m.size() == 0);
for (int i = -100; i <= 100; i = i + 2) {
assert(m.add(i, i) == NULL_TVALUE);
}
testIteratorSteps(m);
for (int i = 100; i > -100; i--) {
if (i % 2 == 0) {
assert(m.remove(i) == i);
}
else {
assert(m.remove(i) == NULL_TVALUE);
}
testIteratorSteps(m);
}
assert(m.size() == 1);
m.remove(-100);
assert(m.size() == 0);
for (int i = -100; i < 100; i++) {
assert(m.add(i, 0) == NULL_TVALUE);
assert(m.add(i, 1) == 0);
assert(m.add(i, 2) == 1);
assert(m.add(i, 3) == 2);
assert(m.add(i, 4) == 3);
}
assert(m.size() == 200);
for (int i = -200; i < 200; i++) {
if (i < -100 || i >= 100) {
assert(m.remove(i) == NULL_TVALUE);
}
else {
assert(m.remove(i) == 4);
assert(m.remove(i) == NULL_TVALUE);
}
}
assert(m.size() == 0);
}
void testIterator() {
cout << "Test iterator" << endl;
Map m;
MapIterator it = m.iterator();
assert(it.valid() == false);
for (int i = 0; i < 100; i++) {
m.add(33, 33);
}
MapIterator it2 = m.iterator();
assert(it2.valid() == true);
TElem el = it2.getCurrent();
assert(el.first == 33);
assert(el.second == 33);
it2.next();
assert(it2.valid() == false);
try {
it2.next();
assert(false);
}
catch (exception&) {
assert(true);
}
try {
it2.getCurrent();
assert(false);
}
catch (exception&) {
assert(true);
}
it2.first();
assert(it2.valid() == true);
Map m2;
for (int i = -100; i < 100; i++) {
assert(m2.add(i, i) == NULL_TVALUE);
assert(m2.add(i, i) == i);
assert(m2.add(i, i) == i);
}
MapIterator it3 = m2.iterator();
assert(it3.valid() == true);
for (int i = 0; i < 200; i++) {
it3.next();
}
assert(it3.valid() == false);
it3.first();
assert(it3.valid() == true);
Map m3;
for (int i = 0; i < 200; i = i + 4) {
m3.add(i, i);
}
MapIterator it4 = m3.iterator();
assert(it4.valid() == true);
int count = 0;
while (it4.valid()) {
TElem e = it4.getCurrent();
assert(e.first % 4 == 0);
it4.next();
count++;
}
assert(count == 50);
}
void testQuantity() {
Map m;
cout << "Test quantity" << endl;
for (int j = 0; j < 30000; j = j + 1) {
assert(m.add(j, j) == NULL_TVALUE);
}
for (int i = 10; i >= 1; i--) {
for (int j = 0; j < 30000; j = j + i) {
assert(m.add(j, j) == j);
}
}
assert(m.size() == 30000);
MapIterator it = m.iterator();
assert(it.valid() == true);
for (int i = 0; i < m.size(); i++) {
it.next();
}
it.first();
while (it.valid()) {
TElem e = it.getCurrent();
assert(m.search(e.first) == e.first);
it.next();
}
assert(it.valid() == false);
for (int j = 30000 - 1; j >= 0; j--) {
assert(m.remove(j) == j);
}
for (int i = 0; i < 10; i++) {
for (int j = 40000; j >= -4000; j--) {
assert(m.remove(j) == NULL_TVALUE);
}
}
assert(m.size() == 0);
}
void testExtra()
{
cout << "Test extra" << endl;
Map m;
assert(m.isEmpty() == true);
assert(m.getKeyRange() == -1);
assert(m.add(1, 2) == NULL_TVALUE);
assert(m.add(1, 3) == 2);
assert(m.add(2, 3) == NULL_TVALUE);
assert(m.getKeyRange() == 1);
assert(m.add(100, 100) == NULL_TVALUE);
assert(m.getKeyRange() == 99);
}
void testAllExtended() {
testCreate();
testAdd();
testRemove();
testIterator();
testQuantity();
testExtra();
}
@@ -0,0 +1,3 @@
#pragma once
void testAllExtended();
@@ -0,0 +1,170 @@
#include "Map.h"
#include "MapIterator.h"
#include <math.h>
#include <iostream>
Map::Map() {
//O(1)
this->_capacity=INITIAL_CAPACITY;
this->_size=0;
this->_elements=new TElem[this->_capacity];
this->_next=new int[this->_capacity];
for(int i=0;i<this->_capacity;i++){
this->_elements[i]=NULL_TELEM;
this->_next[i]=-1;
}
this->_nextFree=INITIAL_CAPACITY-1;
}
Map::~Map() {
//O(1)
delete[] this->_elements;
delete[] this->_next;
}
TValue Map::add(TKey c, TValue v){
// O(1) - amortized
if(this->_size>=this->_capacity*ALPHA)
this->_resize();
int hash=abs(c % this->_capacity);
while(this->_next[hash]!=-1 && this->_elements[hash].first!=c)
hash=this->_next[hash];
if(this->_elements[hash].first==c){
TValue oldValue=this->_elements[hash].second;
this->_elements[hash].second=v;
return oldValue;
}
this->_elements[this->_nextFree]=std::make_pair(c,v);
this->_next[hash]=this->_nextFree;
while(this->_elements[this->_nextFree]!=NULL_TELEM)
this->_nextFree--;
this->_size++;
return NULL_TVALUE;
}
TValue Map::search(TKey c) const{
// O(1) - amortized
int hash = abs(c % this->_capacity);
while (this->_next[hash] != -1 && this->_elements[hash].first != c)
hash = this->_next[hash];
if (this->_elements[hash].first == c)
return this->_elements[hash].second;
return NULL_TVALUE;
}
TValue Map::remove(TKey c){
//O(1) - amortized
int hash = abs(c % this->_capacity);
int prev = -1;
while (this->_next[hash] != -1 && this->_elements[hash].first != c) {
prev = hash;
hash = this->_next[hash];
}
if (this->_elements[hash].first == c) {
TValue oldValue = this->_elements[hash].second;
if (prev == -1) {
if(this->_next[hash]!=-1){
int remove = this->_next[hash];
this->_elements[hash] = this->_elements[this->_next[hash]];
this->_next[hash] = this->_next[this->_next[hash]];
this->_next[remove] = -1;
this->_elements[remove] = NULL_TELEM;
hash = remove;
}
else
this->_elements[hash] = NULL_TELEM;
}
else {
this->_next[prev] = this->_next[hash];
this->_elements[hash] = NULL_TELEM;
this->_next[hash] = -1;
}
if(hash>this->_nextFree)
this->_nextFree = hash;
this->_size--;
return oldValue;
}
return NULL_TVALUE;
}
int Map::size() const {
//O(1)
return this->_size;
}
bool Map::isEmpty() const{
//O(1)
return (this->_size==0);
}
MapIterator Map::iterator() const {
return MapIterator(*this);
}
void Map::_resize() {
//O(n)
int oldCapacity=this->_capacity;
this->_capacity*=2;
while(true){
bool ok=true;
for(int i=2;i<=sqrt(this->_capacity);i++)
if(this->_capacity%i==0){
ok=false;
break;
}
if(ok)
break;
this->_capacity++;
}
TElem* newElements=new TElem[this->_capacity];
int* newNext=new int[this->_capacity];
for(int i=0;i<this->_capacity;i++){
newElements[i]=NULL_TELEM;
newNext[i]=-1;
}
this->_nextFree=this->_capacity-1;
for(int i=0;i<oldCapacity;i++){
if(this->_elements[i]!=NULL_TELEM){
int hash=abs(this->_elements[i].first % this->_capacity);
while(newNext[hash]!=-1)
hash=this->_next[hash];
if(newElements[hash]==NULL_TELEM){
newElements[hash]=this->_elements[i];
newNext[hash]=-1;
}
else{
newElements[this->_nextFree]=this->_elements[i];
newNext[hash]=this->_nextFree;
while(newElements[this->_nextFree]!=NULL_TELEM)
this->_nextFree--;
}
}
}
delete[] this->_elements;
delete[] this->_next;
this->_elements=newElements;
this->_next=newNext;
}
int Map::getKeyRange() const{
//O(n)
MapIterator it = this->iterator();
if (!it.valid())
return -1;
int min = it.getCurrent().first;
int max = it.getCurrent().first;
while (it.valid()) {
if (it.getCurrent().first < min)
min = it.getCurrent().first;
if (it.getCurrent().first > max)
max = it.getCurrent().first;
it.next();
}
return max - min;
}
@@ -0,0 +1,66 @@
#pragma once
#include <utility>
using namespace std;
//DO NOT INCLUDE MAPITERATOR
//DO NOT CHANGE THIS PART
typedef int TKey;
typedef int TValue;
typedef std::pair<TKey, TValue> TElem;
#define NULL_TVALUE -111111
#define NULL_TELEM pair<TKey, TValue>(-111111, -111111)
#define ALPHA 0.75
#define INITIAL_CAPACITY 2300000
class MapIterator;
class Map {
//DO NOT CHANGE THIS PART
friend class MapIterator;
private:
//TODO - Representation
TElem* _elements;
int* _next;
int _size;
int _capacity;
int _nextFree;
void _resize();
public:
// implicit constructor
Map();
// adds a pair (key,value) to the map
//if the key already exists in the map, then the value associated to the key is replaced by the new value and the old value is returned
//if the key does not exist, a new pair is added and the value null is returned
TValue add(TKey c, TValue v);
//searches for the key and returns the value associated with the key if the map contains the key or null: NULL_TVALUE otherwise
TValue search(TKey c) const;
//removes a key from the map and returns the value associated with the key if the key existed ot null: NULL_TVALUE otherwise
TValue remove(TKey c);
//returns the number of pairs (key,value) from the map
int size() const;
//checks whether the map is empty or not
bool isEmpty() const;
//returns an iterator for the map
MapIterator iterator() const;
int getKeyRange() const;
// destructor
~Map();
};
@@ -0,0 +1,55 @@
#include "Map.h"
#include "MapIterator.h"
#include <exception>
using namespace std;
MapIterator::MapIterator(const Map& d) : map(d)
{
//O(1)
this->_current=0;
while (this->_current<this->map._capacity && this->map._elements[this->_current]==NULL_TELEM)
{
this->_current++;
}
this->_first=this->_current;
}
void MapIterator::first() {
//O(1)
this->_current=this->_first;
}
void MapIterator::next() {
//O(1)
if(this->valid()){
this->_current++;
while (this->_current<this->map._capacity && this->map._elements[this->_current]==NULL_TELEM)
{
this->_current++;
}
}
else
throw exception();
}
TElem MapIterator::getCurrent(){
//O(1)
if(this->valid())
return this->map._elements[this->_current];
throw exception();
}
bool MapIterator::valid() const {
//O(1)
if(this->_current<this->map._capacity && this->map._elements[this->_current]!=NULL_TELEM)
return true;
return false;
}
@@ -0,0 +1,21 @@
#pragma once
#include "Map.h"
class MapIterator
{
//DO NOT CHANGE THIS PART
friend class Map;
private:
const Map& map;
//TODO - Representation
int _current;
int _first;
MapIterator(const Map& m);
public:
void first();
void next();
TElem getCurrent();
bool valid() const;
};
@@ -0,0 +1,41 @@
#include "ShortTest.h"
#include <assert.h>
#include "Map.h"
#include "MapIterator.h"
void testAll() { //call each function to see if it is implemented
Map m;
assert(m.isEmpty() == true);
assert(m.size() == 0); //add elements
assert(m.add(5,5)==NULL_TVALUE);
assert(m.add(1,111)==NULL_TVALUE);
assert(m.add(10,110)==NULL_TVALUE);
assert(m.add(7,7)==NULL_TVALUE);
assert(m.add(1,1)==111);
assert(m.add(10,10)==110);
assert(m.add(-3,-3)==NULL_TVALUE);
assert(m.size() == 5);
assert(m.search(10) == 10);
assert(m.search(16) == NULL_TVALUE);
assert(m.remove(1) == 1);
assert(m.remove(6) == NULL_TVALUE);
assert(m.size() == 4);
TElem e;
MapIterator id = m.iterator();
id.first();
int s1 = 0, s2 = 0;
while (id.valid()) {
e = id.getCurrent();
s1 += e.first;
s2 += e.second;
id.next();
}
assert(s1 == 19);
assert(s2 == 19);
}
@@ -0,0 +1,4 @@
#pragma once
void testAll();
@@ -0,0 +1,15 @@
#include "SortedBag.h"
#include "SortedBagIterator.h"
#include <iostream>
#include "ShortTest.h"
#include "ExtendedTest.h"
using namespace std;
int main() {
testAll();
testAllExtended();
cout << "Test over" << endl;
system("pause");
}
@@ -0,0 +1,328 @@
#include "ShortTest.h"
#include "SortedBag.h"
#include "SortedBagIterator.h"
#include <assert.h>
#include <iostream>
#include <exception>
using namespace std;
bool relation2(TComp r1, TComp r2) {
return r1 <= r2;
}
bool relation3(TComp r1, TComp r2) {
return r1 >= r2;
}
void testCreate() {
cout << "Test create" << endl;
SortedBag sb(relation2);
assert(sb.isEmpty() == true);
assert(sb.size() == 0);
for (int i = -10; i < 30; i++) {
assert(sb.remove(i) == false);
}
for (int i = -10; i < 30; i++) {
assert(sb.search(i) == false);
}
for (int i = -10; i < 30; i++) {
assert(sb.nrOccurrences(i) == 0);
}
SortedBagIterator it = sb.iterator();
assert(it.valid() == false);
try {
it.getCurrent();
assert(false);
}
catch (exception&) {
assert(true);
}
try {
it.next();
assert(false);
}
catch (exception&) {
assert(true);
}
}
void testIterator(SortedBag& sb, Relation rel) {
SortedBagIterator it = sb.iterator();
TComp e1;
TComp e2;
if (it.valid()) {
e1 = it.getCurrent();
it.next();
}
while (it.valid()) {
e2 = e1;
e1 = it.getCurrent();
it.next();
assert(sb.search(e1) == true);
assert(sb.search(e2) == true);
assert(sb.nrOccurrences(e1) > 0);
assert(sb.nrOccurrences(e2) > 0);
assert(rel(e2, e1));
}
try {
it.getCurrent();
assert(false);
}
catch (exception&) {
assert(true);
}
try {
it.next();
assert(false);
}
catch (exception&) {
assert(true);
}
it.first();
assert(it.valid() == true);
it.first();
int count = 0;
while (it.valid()) {
count++;
it.next();
}
assert(count == sb.size());
}
void testAdd(Relation r) {
cout << "Test add" << endl;
SortedBag sb(r);
for (int i = 0; i < 100; i++) {
sb.add(i);
}
assert(sb.size() == 100);
assert(sb.isEmpty() == false);
testIterator(sb, r);
for (int i = 200; i >= -200; i--) {
sb.add(i);
}
assert(sb.size() == 501);
testIterator(sb, r);
for (int i = -300; i < 300; i++) {
bool exista = sb.search(i);
int nrA = sb.nrOccurrences(i);
if (i < -200 || i > 200) {
assert(exista == false);
assert(nrA == 0);
}
else if (i >= -200 && i < 0) {
assert(exista == true);
assert(nrA == 1);
}
else if (i >= 0 && i < 100) {
assert(exista == true);
assert(nrA == 2);
}
else if (i >= 100 && i <= 200) {
assert(exista == true);
assert(nrA == 1);
}
}
for (int i = 0; i < 100; i++) {
sb.add(0);
}
assert(sb.nrOccurrences(0) == 102);
testIterator(sb, r);
SortedBag sb2(r);
for (int i = 0; i < 300; i = i + 2) {
sb2.add(i);
sb2.add(2 * i);
sb2.add(-2 * i);
}
assert(sb2.size() == 450);
testIterator(sb2, r);
}
void testRemove(Relation r) {
cout << "Test remove" << endl;
SortedBag sb(r);
for (int i = -100; i < 100; i++) {
assert(sb.remove(i) == false);
assert(sb.search(i) == false);
assert(sb.nrOccurrences(i) == 0);
}
assert(sb.isEmpty() == true);
for (int i = -100; i < 100; i++) {
sb.add(i);
}
assert(sb.size() == 200);
for (int i = -100; i < 100; i = i + 2) {
assert(sb.remove(i) == true);
}
assert(sb.size() == 100);
for (int i = -100; i < 100; i++) {
if (i % 2 == 0) {
assert(sb.nrOccurrences(i) == 0);
assert(sb.search(i) == false);
assert(sb.remove(i) == false);
}
else {
assert(sb.nrOccurrences(i) == 1);
assert(sb.search(i) == true);
}
sb.add(i);
sb.add(i);
sb.add(i);
}
assert(sb.size() == 700);
for (int i = -200; i < 200; i++) {
if (i < -100 || i >= 100) {
assert(sb.search(i) == false);
assert(sb.nrOccurrences(i) == 0);
assert(sb.remove(i) == false);
}
else if (i % 2 == 0) {
assert(sb.search(i) == true);
assert(sb.nrOccurrences(i) == 3);
assert(sb.remove(i) == true);
assert(sb.remove(i) == true);
assert(sb.remove(i) == true);
assert(sb.remove(i) == false);
}
else {
assert(sb.search(i) == true);
assert(sb.nrOccurrences(i) == 4);
assert(sb.remove(i) == true);
assert(sb.remove(i) == true);
assert(sb.remove(i) == true);
assert(sb.remove(i) == true);
assert(sb.remove(i) == false);
}
}
SortedBag sb2(r);
for (int i = 300; i >= -500; i--) {
sb2.add(i);
sb2.add(i * 2);
sb2.add(-2 * i);
}
for (int i = -100; i < 100; i++) {
for (int j = 0; j < 100; j++) {
sb2.remove(i);
}
}
for (int i = -100; i < 0; i++) {
assert(sb2.nrOccurrences(i) == 0);
assert(sb2.search(i) == false);
}
}
void testQuantity(Relation r) {
cout << "Test quantity" << endl;
SortedBag sb(r);
for (int j = 0; j < 10; j++) {
sb.add(0);
for (int i = 1; i < 300; i++) {
sb.add(i);
sb.add(-i);
}
sb.add(-3000);
}
int count = 6000;
assert(sb.size() == 6000);
for (int i = 0; i < 5000; i++) {
TComp nr = rand() % 8000 - 4000;
if (sb.remove(nr) == true) {
count--;
}
assert(sb.size() == count);
}
assert(sb.size() == count);
}
void testIterator(Relation rel) {
cout << "Test iterator" << endl;
SortedBag sb(rel);
for (int i = 0; i < 500; i++) {
sb.add(i);
sb.add(-2 * i);
sb.add(2 * i);
sb.add(i);
sb.add(-2 * i);
sb.add(2 * i);
}
assert(sb.size() == 3000);
SortedBagIterator sbi = sb.iterator();
int count = 0;
while (sbi.valid()) {
count++;
sbi.next();
}
assert(count == sb.size());
sbi.first();
TElem e = sbi.getCurrent();
sbi.next();
count = 1;
while (sbi.valid()) {
TElem ee = sbi.getCurrent();
assert(rel(e, ee));
TElem ee2 = sbi.getCurrent();
assert(ee == ee2);
TElem ee3 = sbi.getCurrent();
assert(ee == ee3);
e = ee;
sbi.next();
count++;
}
assert(count == sb.size());
}
void testExtra(){
cout << "Test extra" << endl;
SortedBag sb(relation2);
sb.add(2);
sb.add(2);
sb.add(2);
sb.add(1);
sb.add(1);
sb.add(1);
sb.add(1);
sb.add(2);
sb.add(5);
sb.add(3);
sb.add(4);
assert(sb.size() == 11);
assert(sb.nrOccurrences(1) == 4);
assert(sb.nrOccurrences(2) == 4);
assert(sb.nrOccurrences(3) == 1);
assert(sb.nrOccurrences(4) == 1);
assert(sb.nrOccurrences(5) == 1);
assert(sb.elementsWithThisFrequency(1) == 3);
assert(sb.elementsWithThisFrequency(4) == 2);
try {
sb.elementsWithThisFrequency(0);
assert(false);
}
catch (exception&) {
assert(true);
}
}
void testAllExtended() {
testCreate();
testAdd(relation2);
testAdd(relation3);
testRemove(relation2);
testRemove(relation3);
testIterator(relation2);
testIterator(relation3);
testQuantity(relation2);
testQuantity(relation3);
testExtra();
}
@@ -0,0 +1,3 @@
#pragma once
void testAllExtended();
@@ -0,0 +1,39 @@
#include "ShortTest.h"
#include "SortedBag.h"
#include "SortedBagIterator.h"
#include <assert.h>
bool relation1(TComp e1, TComp e2) {
return e1 <= e2;
}
void testAll() {
SortedBag sb(relation1);
sb.add(5);
sb.add(6);
sb.add(0);
sb.add(5);
sb.add(10);
sb.add(8);
assert(sb.size() == 6);
assert(sb.nrOccurrences(5) == 2);
assert(sb.remove(5) == true);
assert(sb.size() == 5);
assert(sb.search(6) == true);
assert(sb.isEmpty() == false);
SortedBagIterator it = sb.iterator();
assert(it.valid() == true);
while (it.valid()) {
it.getCurrent();
it.next();
}
assert(it.valid() == false);
it.first();
assert(it.valid() == true);
}
@@ -0,0 +1,3 @@
#pragma once
void testAll();
@@ -0,0 +1,239 @@
#include "SortedBag.h"
#include "SortedBagIterator.h"
#include <exception>
SortedBag::SortedBag(Relation r) {
//TODO - Implementation
this->relation = r;
this->root = nullptr;
this->length = 0;
}
void SortedBag::add(TComp e) {
//Best case: O(1) Worst case: O(n) Average case: O(log n)
BSTNode* newNode = new BSTNode;
newNode->elem = e;
newNode->left = nullptr;
newNode->right = nullptr;
newNode->parent = nullptr;
newNode->count = 1;
if (this->root == nullptr) {
this->root = newNode;
this->length++;
return;
}
BSTNode* current = this->root;
while (current != nullptr) {
if (current->elem == e) {
current->count++;
this->length++;
return;
}
if (this->relation(e, current->elem)) {
if (current->left == nullptr) {
current->left = newNode;
newNode->parent = current;
this->length++;
return;
}
else {
current = current->left;
}
}
else {
if (current->right == nullptr) {
current->right = newNode;
newNode->parent = current;
this->length++;
return;
}
else {
current = current->right;
}
}
}
}
bool SortedBag::remove(TComp e) {
//Best case: O(1) Worst case: O(n) Average case: O(log n)
BSTNode* current = this->root;
while (current != nullptr) {
if(current->elem==e){
if(current->count>1){
current->count--;
this->length--;
return true;
}
else{
if(current->left==nullptr && current->right==nullptr){
if(current->parent==nullptr){
this->root=nullptr;
this->length--;
return true;
}
else{
if(current->parent->left==current){
current->parent->left=nullptr;
this->length--;
return true;
}
else{
current->parent->right=nullptr;
this->length--;
return true;
}
}
}
else{
if(current->left==nullptr){
if(current->parent==nullptr){
this->root=current->right;
this->root->parent=nullptr;
this->length--;
return true;
}
else{
if(current->parent->left==current){
current->parent->left=current->right;
this->length--;
return true;
}
else{
current->parent->right=current->right;
this->length--;
return true;
}
}
}
else{
if(current->right==nullptr){
if(current->parent==nullptr){
this->root=current->left;
this->root->parent=nullptr;
this->length--;
return true;
}
else{
if(current->parent->left==current){
current->parent->left=current->left;
this->length--;
return true;
}
else{
current->parent->right=current->left;
this->length--;
return true;
}
}
}
else{
BSTNode* current2=current->right;
while(current2->left!=nullptr){
current2=current2->left;
}
current->elem=current2->elem;
current->count=current2->count;
if(current2->parent->left==current2){
current2->parent->left=current2->right;
this->length--;
return true;
}
else{
current2->parent->right=current2->right;
this->length--;
return true;
}
}
}
}
}
}
else{
if(this->relation(e,current->elem)){
current=current->left;
}
else{
current=current->right;
}
}
}
return false;
}
bool SortedBag::search(TComp elem) const {
// Best case: O(1) Worst case: O(n) Average case: O(log n)
BSTNode* current = this->root;
while (current != nullptr) {
if (current->elem == elem) {
return true;
}
if (this->relation(elem, current->elem)) {
current = current->left;
}
else {
current = current->right;
}
}
return false;
}
int SortedBag::nrOccurrences(TComp elem) const {
// Best case: O(1) Worst case: O(n) Average case: O(log n)
BSTNode* current = this->root;
while (current != nullptr) {
if (current->elem == elem) {
return current->count;
}
if (this->relation(elem, current->elem)) {
current = current->left;
}
else {
current = current->right;
}
}
return 0;
}
int SortedBag::size() const {
//O(1)
return this->length;
}
bool SortedBag::isEmpty() const {
//O(1)
return (this->length == 0);
}
SortedBagIterator SortedBag::iterator() const {
return SortedBagIterator(*this);
}
SortedBag::~SortedBag() {
//O(n)
delete this->root;
}
int SortedBag::elementsWithThisFrequency(int frequency) const {
// O(n)
if(frequency<=0){
throw std::exception();
}
return reccuriveCount(this->root,frequency);
}
int SortedBag::reccuriveCount(BSTNode* node, int frequency) const {
if(node==nullptr){
return 0;
}
return reccuriveCount(node->left,frequency)+reccuriveCount(node->right, frequency) + (this->nrOccurrences(node->elem)==frequency);
}
@@ -0,0 +1,65 @@
#pragma once
//DO NOT INCLUDE SORTEDBAGITERATOR
//DO NOT CHANGE THIS PART
typedef int TComp;
typedef TComp TElem;
typedef bool(*Relation)(TComp, TComp);
#define NULL_TCOMP -11111;
class BSTNode {
public:
TComp elem;
BSTNode* left;
BSTNode* right;
BSTNode* parent;
~BSTNode() {
delete left;
delete right;
}
int count;
};
class SortedBagIterator;
class SortedBag {
friend class SortedBagIterator;
private:
//TODO - Representation
BSTNode* root;
Relation relation;
int length;
int reccuriveCount(BSTNode* node, int frequency) const;
public:
//constructor
SortedBag(Relation r);
//adds an element to the sorted bag
void add(TComp e);
//removes one occurence of an element from a sorted bag
//returns true if an element was removed, false otherwise (if e was not part of the sorted bag)
bool remove(TComp e);
//checks if an element appearch is the sorted bag
bool search(TComp e) const;
//returns the number of occurrences for an element in the sorted bag
int nrOccurrences(TComp e) const;
//returns the number of elements from the sorted bag
int size() const;
//returns an iterator for this sorted bag
SortedBagIterator iterator() const;
//checks if the sorted bag is empty
bool isEmpty() const;
//destructor
~SortedBag();
int elementsWithThisFrequency(int frequency) const;
};
@@ -0,0 +1,73 @@
#include "SortedBagIterator.h"
#include "SortedBag.h"
#include <exception>
using namespace std;
SortedBagIterator::SortedBagIterator(const SortedBag& b) : bag(b) {
// Best case: O(1) Worst case: O(n) Average case: O(log n)
this->first();
}
TComp SortedBagIterator::getCurrent() {
//O(1)
if(this->valid())
return this->current->elem;
else
throw exception();
}
bool SortedBagIterator::valid() {
//O(1)
if(this->current == nullptr)
return false;
return true;
}
void SortedBagIterator::next() {
// Best case: O(1) Worst case: O(n) Average case: O(log n)
if(this->valid())
{
if(this->currentCount > 1)
this->currentCount--;
else
{
if(this->current->right != nullptr)
{
this->current = this->current->right;
while(this->current->left != nullptr)
this->current = this->current->left;
this->currentCount = this->current->count;
}
else
{
BSTNode* currentParent = this->current->parent;
while(currentParent != nullptr && currentParent->right == this->current)
{
this->current = currentParent;
currentParent = currentParent->parent;
}
this->current = currentParent;
if(this->current != nullptr)
this->currentCount = this->current->count;
else
this->currentCount = 0;
}
}
}
else
throw exception();
}
void SortedBagIterator::first() {
// Best case: O(1) Worst case: O(n) Average case: O(log n)
this->current = this->bag.root;
if(this->current != nullptr){
while(this->current->left != nullptr)
this->current = this->current->left;
this->currentCount = this->current->count;
}
else{
this->currentCount = 0;
}
}
@@ -0,0 +1,24 @@
#pragma once
#include "SortedBag.h"
class SortedBag;
class SortedBagIterator
{
friend class SortedBag;
private:
const SortedBag& bag;
SortedBagIterator(const SortedBag& b);
//TODO - Representation
BSTNode* current;
int currentCount;
public:
TComp getCurrent();
bool valid();
void next();
void first();
};
@@ -0,0 +1,39 @@
class Bag:
def __init__(self):
self.__elements = []
def add(self, e):
self.__elements.append(e)
def remove(self, e):
if e in self.__elements:
self.__elements.remove(e)
return True
return False
def search(self, e):
return e in self.__elements
def size(self):
return len(self.__elements)
def nrOccurrences(self, e):
return self.__elements.count(e)
def destroy(self):
del(self)
def iterator(self):
return BagIterator(self.__elements)
class BagIterator:
def __init__(self, elements):
self.__elements = elements
self.__current = 0
def first(self):
self.__current = 0
def valid(self):
return self.__current < len(self.__elements)
def next(self):
if self.valid():
self.__current += 1
def getCurrent(self):
if self.valid():
return self.__elements[self.__current]
else:
raise ValueError("Invalid iterator position.")
@@ -0,0 +1,46 @@
from Bag import Bag, BagIterator
def createIntBag():
intBag=Bag()
intBag.add(6)
intBag.add(11)
intBag.add(77)
intBag.add(7)
intBag.add(4)
intBag.add(6)
intBag.add(77)
intBag.add(6)
return intBag
def createStringBag():
stringBag=Bag()
stringBag.add("data")
stringBag.add("structures")
stringBag.add("and")
stringBag.add("algorithms")
stringBag.add("data")
stringBag.add("data")
stringBag.add("algorithms")
return stringBag
def printBag(bag):
it = bag.iterator()
while it.valid():
print(it.getCurrent())
it.next()
print("Over. Let's start again.")
it.first()
while it.valid():
print(it.getCurrent())
it.next()
def main():
b1 = createIntBag()
printBag(b1)
print("No occurrences of 77: ", b1.nrOccurrences(77))
b2 = createStringBag()
printBag(b2)
print("No occurrences of 'data': ", b2.nrOccurrences("data"))
if __name__ == "__main__":
main()
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,224 @@
#include "directed_graph.h"
#include <unordered_set>
#include <unordered_map>
#include <string>
#include <fstream>
DirectedGraph::DirectedGraph(){
// nothing to do
}
DirectedGraph::~DirectedGraph(){
// nothing to do
}
DirectedGraph::DirectedGraph(const DirectedGraph& g){
this->_vertices = g._vertices;
this->_inbounds.clear();
this->_outbounds.clear();
this->_weights.clear();
for(std::pair<const int, std::unordered_set<int>> p : g._inbounds){
this->_inbounds[p.first] = p.second;
}
for(std::pair<const int, std::unordered_set<int>> p : g._outbounds){
this->_outbounds[p.first] = p.second;
}
for(std::pair<const std::pair<int, int>, int> p : g._weights){
this->_weights[p.first] = p.second;
}
}
DirectedGraph DirectedGraph::operator=(const DirectedGraph& g){
this->_vertices = g._vertices;
this->_inbounds.clear();
this->_outbounds.clear();
this->_weights.clear();
for(std::pair<const int, std::unordered_set<int>> p : g._inbounds){
this->_inbounds[p.first] = p.second;
}
for(std::pair<const int, std::unordered_set<int>> p : g._outbounds){
this->_outbounds[p.first] = p.second;
}
for(std::pair<const std::pair<int, int>, int> p : g._weights){
this->_weights[p.first] = p.second;
}
return *this;
}
DirectedGraph DirectedGraph::reindex() const{
std::unordered_map<int, int> old_to_new;
int i = this->numVertices()-1;
for(int v : this->_vertices){
old_to_new[v] = i;
i--;
}
DirectedGraph new_g;
for(int v : this->_vertices){
new_g.addVertex(old_to_new[v]);
}
for(std::pair<const std::pair<int, int>, int> p : this->_weights){
new_g.addEdge(old_to_new[p.first.first], old_to_new[p.first.second], p.second);
}
return new_g;
}
int DirectedGraph::numVertices() const{
return this->_vertices.size();
}
int DirectedGraph::numEdges() const{
return this->_weights.size();
}
std::unordered_set<int> DirectedGraph::vertices() const{
return this->_vertices;
}
std::unordered_map<std::pair<int, int>, int> DirectedGraph::edges() const{
std::unordered_map<std::pair<int, int>, int> weights;
for(std::pair<const std::pair<int, int>, int> p : this->_weights){
weights[p.first] = p.second;
}
return weights;
}
bool DirectedGraph::isEdge(int v1, int v2) const{
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_weights.find(std::make_pair(v1, v2)) != this->_weights.end();
}
int DirectedGraph::inDegree(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_inbounds.at(v).size();
}
int DirectedGraph::outDegree(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_outbounds.at(v).size();
}
std::unordered_set<int> DirectedGraph::inbounds(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_inbounds.at(v);
}
std::unordered_set<int> DirectedGraph::outbounds(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_outbounds.at(v);
}
int DirectedGraph::weight(int v1, int v2) const{
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) == this->_weights.end())
throw std::invalid_argument("Edge not found");
return this->_weights.at(std::make_pair(v1, v2));
}
void DirectedGraph::weight(int v1, int v2, int w){
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) == this->_weights.end())
throw std::invalid_argument("Edge not found");
this->_weights[std::make_pair(v1, v2)] = w;
}
void DirectedGraph::addVertex(int v){
if(this->_vertices.find(v) != this->_vertices.end())
throw std::invalid_argument("Vertex already exists");
this->_vertices.insert(v);
this->_inbounds[v] = std::unordered_set<int>();
this->_outbounds[v] = std::unordered_set<int>();
}
void DirectedGraph::removeVertex(int v){
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
this->_vertices.erase(v);
for(int i : this->_inbounds[v]){
this->_outbounds[i].erase(v);
this->_weights.erase(std::make_pair(i, v));
}
for(int i : this->_outbounds[v]){
this->_inbounds[i].erase(v);
this->_weights.erase(std::make_pair(v, i));
}
this->_inbounds.erase(v);
this->_outbounds.erase(v);
}
void DirectedGraph::addEdge(int v1, int v2, int w){
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) != this->_weights.end())
throw std::invalid_argument("Edge already exists");
this->_weights[std::make_pair(v1, v2)] = w;
this->_inbounds[v2].insert(v1);
this->_outbounds[v1].insert(v2);
}
void DirectedGraph::removeEdge(int v1, int v2){
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) == this->_weights.end())
throw std::invalid_argument("Edge not found");
this->_weights.erase(std::make_pair(v1, v2));
this->_inbounds[v2].erase(v1);
this->_outbounds[v1].erase(v2);
}
DirectedGraph read_from_file(std::string filename){
std::ifstream file(filename);
if(!file.is_open())
throw std::invalid_argument("File not found");
DirectedGraph g;
int num_vertices=0;
file >> num_vertices;
for(int i = 0; i < num_vertices; i++){
g.addVertex(i);
}
int num_edges=0;
file >> num_edges;
int v1, v2, w;
for(int i = 0; i < num_edges; i++){
file >> v1 >> v2 >> w;
g.addEdge(v1, v2, w);
}
file.close();
return g;
}
void write_to_file(const DirectedGraph& g, std::string filename){
DirectedGraph new_g = g.reindex();
std::ofstream file(filename);
if(!file.is_open())
throw std::invalid_argument("File could not be opened");
file << new_g.numVertices() << " " << new_g.numEdges() << std::endl;
for(std::pair<const std::pair<int, int>, int> p : new_g.edges()){
file << p.first.first << " " << p.first.second << " " << p.second << std::endl;
}
file.close();
}
DirectedGraph random_graph(int num_vertices, int num_edges){
DirectedGraph g;
for(int i = 0; i < num_vertices; i++){
g.addVertex(i);
}
for(int i = 0; i < num_edges; i++){
int v1 = rand() % num_vertices;
int v2 = rand() % num_vertices;
int w = rand() % 100;
if (g.isEdge(v1, v2)){
i--;
continue;
}
g.addEdge(v1, v2, w);
}
return g;
}
@@ -0,0 +1,47 @@
#pragma once
#include<unordered_set>
#include<unordered_map>
#include<string>
namespace std{
template<>
struct hash<std::pair<int,int>>{
size_t operator()(const std::pair<int,int>& p) const{
return (std::hash<int>()(p.first)<<1) ^ std::hash<int>()(p.second);
}
};
}
class DirectedGraph{
private:
std::unordered_set<int> _vertices;
std::unordered_map<int,std::unordered_set<int>> _inbounds;
std::unordered_map<int,std::unordered_set<int>> _outbounds;
std::unordered_map<std::pair<int,int>,int> _weights;
public:
DirectedGraph();
~DirectedGraph();
DirectedGraph(const DirectedGraph& g);
DirectedGraph operator=(const DirectedGraph& g);
DirectedGraph reindex() const;
int numVertices() const;
int numEdges() const;
std::unordered_set<int> vertices() const;
std::unordered_map<std::pair<int,int>,int> edges() const;
bool isEdge(int v1, int v2) const;
int inDegree(int v) const;
int outDegree(int v) const;
std::unordered_set<int> inbounds(int v) const;
std::unordered_set<int> outbounds(int v) const;
int weight(int v1, int v2) const;
void weight(int v1, int v2, int w);
void addVertex(int v);
void removeVertex(int v);
void addEdge(int v1, int v2, int w);
void removeEdge(int v1, int v2);
};
DirectedGraph read_from_file(std::string filename);
void write_to_file(const DirectedGraph& g, std::string filename);
DirectedGraph random_graph(int num_vertices, int num_edges);
@@ -0,0 +1,12 @@
#include "directed_graph.h"
#include "ui.h"
#include <utility>
#include <vector>
#include <unordered_map>
#include <iostream>
int main(){
UI ui;
ui.run();
return 0;
}
@@ -0,0 +1,282 @@
#include "directed_graph.h"
#include "ui.h"
#include <unordered_set>
#include <unordered_map>
#include <iostream>
UI::UI(){
// nothing to do
}
UI::~UI(){
// nothing to do
}
void UI::run(){
int command;
while(true){
if(this->_graph.numVertices() == 0)
std::cout << std::endl << "Graph is empty" << std::endl;
std::cout << std::endl;
std::cout << "1. Load graph from file" << std::endl;
std::cout << "2. Save graph to file" << std::endl;
std::cout << "3. Generate a graph" << std::endl;
std::cout << "4. Add vertex" << std::endl;
std::cout << "5. Remove vertex" << std::endl;
std::cout << "6. Add edge" << std::endl;
std::cout << "7. Remove edge" << std::endl;
std::cout << "8. Get in degree" << std::endl;
std::cout << "9. Get out degree" << std::endl;
std::cout << "10. Get cost" << std::endl;
std::cout << "11. Set cost" << std::endl;
std::cout << "12. Get number of vertices" << std::endl;
std::cout << "13. Get number of edges" << std::endl;
std::cout << "14. Get vertices" << std::endl;
std::cout << "15. Get edges" << std::endl;
std::cout << "16. Get inbounds" << std::endl;
std::cout << "17. Get outbounds" << std::endl;
std::cout << "18. Futeti-l " << std::endl;
std::cout << "0. Exit" << std::endl;
std::cout << "Command: ";
std::cin >> command;
std::cout << std::endl;
switch(command){
case 1:{
std::string filename;
std::cout << "Filename: ";
std::cin >> filename;
try{
this->_graph = read_from_file(filename);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 2:{
std::string filename;
std::cout << "Filename: ";
std::cin >> filename;
try{
write_to_file(this->_graph, filename);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 3:{
int num_vertices, num_edges;
std::cout << "Number of vertices: ";
std::cin >> num_vertices;
std::cout << "Number of edges: ";
std::cin >> num_edges;
try{
this->_graph = random_graph(num_vertices, num_edges);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 4:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
this->_graph.addVertex(v);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 5:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
this->_graph.removeVertex(v);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 6:{
int v1, v2, w;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
std::cout << "Weight: ";
std::cin >> w;
try{
this->_graph.addEdge(v1, v2, w);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 7:{
int v1, v2;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
try{
this->_graph.removeEdge(v1, v2);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 8:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::cout << "In degree: " << this->_graph.inDegree(v) << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 9:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::cout << "Out degree: " << this->_graph.outDegree(v) << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 10:{
int v1, v2;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
try{
std::cout << "Cost: " << this->_graph.weight(v1, v2) << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 11:{
int v1, v2, w;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
std::cout << "Weight: ";
std::cin >> w;
try{
this->_graph.weight(v1, v2, w);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 12:{
std::cout << "Number of vertices: " << this->_graph.numVertices() << std::endl;
break;
}
case 13:{
std::cout << "Number of edges: " << this->_graph.numEdges() << std::endl;
break;
}
case 14:{
std::unordered_set<int> vertices = this->_graph.vertices();
for(int vertex : vertices){
std::cout << vertex << " ";
}
std::cout << std::endl;
break;
}
case 15:{
std::unordered_map<std::pair<int, int>, int> edges = this->_graph.edges();
for(std::pair<std::pair<int, int>, int> edge : edges){
std::cout << edge.first.first << " " << edge.first.second << " " << edge.second << std::endl;
}
break;
}
case 16:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::unordered_set<int> inbounds = this->_graph.inbounds(v);
for(int vertex : inbounds){
std::cout << vertex << " ";
}
std::cout << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 17:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::unordered_set<int> outbounds = this->_graph.outbounds(v);
for(int vertex : outbounds){
std::cout << vertex << " ";
}
std::cout << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 18:{
std::cout<<"Inbound: \n";
std::unordered_set<int> vertices = this->_graph.vertices();
for(int vertex : vertices){
std::cout << vertex << ": ";
for(int in : this->_graph.inbounds(vertex)){
std::cout << in << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
vertices = this->_graph.vertices();
std::cout<<"Outbound: \n";
for(int vertex : vertices){
std::cout << vertex << ": ";
for(int out : this->_graph.outbounds(vertex)){
std::cout << out << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
std::cout<<"Edges: \n";
std::unordered_map<std::pair<int, int>, int> edges = this->_graph.edges();
for(std::pair<std::pair<int, int>, int> edge : edges){
std::cout << edge.first.first << " " << edge.first.second << " " << edge.second << std::endl;
}
break;
}
case 0:{
return;
}
default:{
std::cout << "Invalid command" << std::endl;
break;
}
}
}
}
@@ -0,0 +1,11 @@
#pragma once
#include "directed_graph.h"
class UI{
private:
DirectedGraph _graph;
public:
UI();
~UI();
void run();
};
@@ -0,0 +1,160 @@
package DirectedGraphJava;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Iterator;
public class DirectedGraph implements IDirectedGraph {
private HashSet<Integer> _vertices = new HashSet<Integer>();
private HashMap<Integer, HashSet<Integer>> _inbounds = new HashMap<Integer, HashSet<Integer>>();
private HashMap<Integer, HashSet<Integer>> _outbounds = new HashMap<Integer, HashSet<Integer>>();
private HashMap<Pair<Integer,Integer>,Integer> _edges = new HashMap<Pair<Integer,Integer>,Integer>();
public DirectedGraph() {
//nothing to do
}
public DirectedGraph reindex(){
HashMap<Integer,Integer> oldToNew = new HashMap<Integer,Integer>();
int i = 0;
for (Integer vertex : _vertices) {
oldToNew.put(vertex,i);
i++;
}
DirectedGraph newGraph = new DirectedGraph();
for (Integer vertex : _vertices) {
newGraph.addVertex(oldToNew.get(vertex));
}
for (Pair<Integer,Integer> edge : _edges.keySet()) {
newGraph.addEdge(oldToNew.get(edge.first),oldToNew.get(edge.second),_edges.get(edge));
}
return newGraph;
}
public Integer numVertices() {
return _vertices.size();
}
public Integer numEdges() {
return _edges.size();
}
public Iterator<Integer> vertices() {
return _vertices.iterator();
}
public Iterator<Pair<Pair<Integer,Integer>,Integer>> edges() {
HashSet<Pair<Pair<Integer,Integer>,Integer>> keyValues = new HashSet<Pair<Pair<Integer,Integer>,Integer>>();
for (Pair<Integer,Integer> key : this._edges.keySet()) {
Pair<Pair<Integer,Integer>,Integer> keyValuePair = new Pair<Pair<Integer,Integer>,Integer>(key,this._edges.get(key));
keyValues.add(keyValuePair);
}
return keyValues.iterator();
}
public boolean isEdge(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _edges.containsKey(new Pair<Integer,Integer>(v1,v2));
}
public int inDegree(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _inbounds.get(v).size();
}
public int outDegree(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _outbounds.get(v).size();
}
public Iterator<Integer> inbounds(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _inbounds.get(v).iterator();
}
public Iterator<Integer> outbounds(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _outbounds.get(v).iterator();
}
public Integer weight(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
return _edges.get(new Pair<Integer,Integer>(v1,v2));
}
public void weight(Integer v1, Integer v2, Integer w) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
_edges.put(new Pair<Integer,Integer>(v1,v2),w);
}
public void addVertex(Integer v) {
if(_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex already exists");
}
_vertices.add(v);
_inbounds.put(v,new HashSet<Integer>());
_outbounds.put(v,new HashSet<Integer>());
}
public void removeVertex(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
_vertices.remove(v);
for (Integer vertex : _inbounds.get(v)) {
_outbounds.get(vertex).remove(v);
_edges.remove(new Pair<Integer,Integer>(vertex,v));
}
for (Integer vertex : _outbounds.get(v)) {
_inbounds.get(vertex).remove(v);
_edges.remove(new Pair<Integer,Integer>(v,vertex));
}
_inbounds.remove(v);
_outbounds.remove(v);
}
public void addEdge(Integer v1, Integer v2, Integer w) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge already exists");
}
_edges.put(new Pair<Integer,Integer>(v1,v2),w);
_inbounds.get(v2).add(v1);
_outbounds.get(v1).add(v2);
}
public void removeEdge(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
_edges.remove(new Pair<Integer,Integer>(v1,v2));
_inbounds.get(v2).remove(v1);
_outbounds.get(v1).remove(v2);
}
}
@@ -0,0 +1,22 @@
package DirectedGraphJava;
import java.util.Iterator;
interface IDirectedGraph {
public DirectedGraph reindex();
public Integer numVertices();
public Integer numEdges();
public Iterator<Integer> vertices();
public Iterator<Pair<Pair<Integer,Integer>,Integer>> edges();
public boolean isEdge(Integer v1, Integer v2);
public int inDegree(Integer v);
public int outDegree(Integer v);
public Iterator<Integer> inbounds(Integer v);
public Iterator<Integer> outbounds(Integer v);
public Integer weight(Integer v1, Integer v2);
public void weight(Integer v1, Integer v2, Integer w);
public void addVertex(Integer v);
public void removeVertex(Integer v);
public void addEdge(Integer v1, Integer v2, Integer w);
public void removeEdge(Integer v1, Integer v2);
}
@@ -0,0 +1,68 @@
package DirectedGraphJava;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
public class Main {
public static DirectedGraph read_from_file(String filename) throws FileNotFoundException {
DirectedGraph graph = new DirectedGraph();
File file = new File(filename);
Scanner scanner = new Scanner(file);
Integer num_vertices = scanner.nextInt();
for(Integer i = 0; i < num_vertices; i++)
graph.addVertex(i);
Integer num_edges = scanner.nextInt();
for(Integer i = 0; i < num_edges; i++){
Integer v1 = scanner.nextInt();
Integer v2 = scanner.nextInt();
Integer w = scanner.nextInt();
graph.addEdge(v1, v2, w);
}
scanner.close();
return graph;
}
public static void write_to_file(DirectedGraph graph, String filename) throws IOException {
DirectedGraph new_graph = graph.reindex();
File file = new File(filename);
file.createNewFile();
FileWriter writer = new FileWriter(file);
writer.write(new_graph.numVertices().toString() + " " + new_graph.numEdges().toString() + "\n");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = new_graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
writer.write(e.first.first.toString() + " " + e.first.second.toString() + " " + e.second.toString() + "\n");
}
writer.close();
}
public static DirectedGraph random_graph(Integer num_vertices, Integer num_edges) {
DirectedGraph graph = new DirectedGraph();
for(Integer i = 0; i < num_vertices; i++)
graph.addVertex(i);
for(Integer i = 0; i < num_edges; i++){
Integer v1 = (int)(Math.random() * num_vertices);
Integer v2 = (int)(Math.random() * num_vertices);
Integer w = (int)(Math.random() * 100);
if(graph.isEdge(v1, v2)){
i--;
continue;
}
graph.addEdge(v1, v2, w);
}
return graph;
}
public static void main(String[] args) {
ui UI = new ui();
UI.run();
}
}
@@ -0,0 +1,30 @@
package DirectedGraphJava;
public class Pair<T1,T2> {
public T1 first;
public T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair<?, ?> pair = (Pair<?, ?>) o;
if (first != null ? !first.equals(pair.first) : pair.first != null) return false;
return second != null ? second.equals(pair.second) : pair.second == null;
}
@Override
public int hashCode() {
int result = first != null ? first.hashCode() : 0;
result = 31 * result + (second != null ? second.hashCode() : 0);
return result;
}
}
@@ -0,0 +1,260 @@
package DirectedGraphJava;
import java.util.Iterator;
public class ui {
private DirectedGraph graph = new DirectedGraph();
public ui(){
}
public void run(){
Integer command;
while(true){
if(this.graph.numVertices() == 0)
System.out.println("Graph is empty");
System.out.println();
System.out.println("1. Load graph from file");
System.out.println("2. Save graph to file");
System.out.println("3. Generate a graph");
System.out.println("4. Add a vertex");
System.out.println("5. Remove a vertex");
System.out.println("6. Add an edge");
System.out.println("7. Remove an edge");
System.out.println("8. Get in degree");
System.out.println("9. Get out degree");
System.out.println("10 Get cost");
System.out.println("11. Set cost");
System.out.println("12. Get number of vertices");
System.out.println("13. Get number of edges");
System.out.println("14. Get vertices");
System.out.println("15. Get edges");
System.out.println("16. Get inbounds");
System.out.println("17. Get outbounds");
System.out.println("18. Futeti-l");
System.out.println("0. Exit");
System.out.print("Command: ");
command = Integer.parseInt(System.console().readLine());
System.out.println();
switch(command){
case 1: {
System.out.print("File name: ");
String fileName = System.console().readLine();
try{
this.graph = Main.read_from_file(fileName);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 2: {
System.out.print("File name: ");
String fileName = System.console().readLine();
try{
Main.write_to_file(this.graph, fileName);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 3: {
System.out.print("Number of vertices: ");
Integer numVertices = Integer.parseInt(System.console().readLine());
System.out.print("Number of edges: ");
Integer numEdges = Integer.parseInt(System.console().readLine());
try{
this.graph = Main.random_graph(numVertices, numEdges);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 4: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
this.graph.addVertex(vertex);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 5: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
this.graph.removeVertex(vertex);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 6: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
System.out.print("Weight: ");
Integer weight = Integer.parseInt(System.console().readLine());
try{
this.graph.addEdge(vertex1, vertex2, weight);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 7: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
try{
this.graph.removeEdge(vertex1, vertex2);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 8: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
System.out.println("In degree: " + this.graph.inDegree(vertex));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 9: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
System.out.println("Out degree: " + this.graph.outDegree(vertex));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 10: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
try{
System.out.println("Cost: " + this.graph.weight(vertex1, vertex2));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 11: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
System.out.print("Weight: ");
Integer weight = Integer.parseInt(System.console().readLine());
try{
this.graph.weight(vertex1, vertex2, weight);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 12: {
System.out.println("Number of vertices: " + this.graph.numVertices());
break;
}
case 13: {
System.out.println("Number of edges: " + this.graph.numEdges());
break;
}
case 14: {
System.out.println("Vertices: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
System.out.println(vertex.next());
}
break;
}
case 15: {
System.out.println("Edges: ");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = this.graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
System.out.println(e.first.first + " " + e.first.second + " " + e.second);
}
break;
}
case 16: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Inbounds: ");
for(Iterator<Integer> inbounds = this.graph.inbounds(vertex); inbounds.hasNext();){
Integer e = inbounds.next();
System.out.println(e);
}
break;
}
case 17: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Outbounds: ");
for(Iterator<Integer> outbounds = this.graph.outbounds(vertex); outbounds.hasNext();){
Integer e = outbounds.next();
System.out.println(e);
}
break;
}
case 18:{
System.out.println("Inbounds: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
Integer v = vertex.next();
System.out.print(v);
System.out.print(": ");
for(Iterator<Integer> inbounds = this.graph.inbounds(v); inbounds.hasNext();){
Integer e = inbounds.next();
System.out.print(e);
System.out.print(" ");
}
System.out.println();
}
System.out.println();
System.out.println("Outbounds: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
Integer v = vertex.next();
System.out.print(v);
System.out.print(": ");
for(Iterator<Integer> outbounds = this.graph.outbounds(v); outbounds.hasNext();){
Integer e = outbounds.next();
System.out.print(e);
System.out.print(" ");
}
System.out.println();
}
System.out.println();
System.out.println("Edges: ");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = this.graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
System.out.println(e.first.first + " " + e.first.second + " " + e.second);
}
break;
}
case 0:{
System.exit(0);
}
default: {
System.out.println("Invalid option");
break;
}
}
}
}
}
@@ -0,0 +1,7 @@
5 6
0 0 1
0 1 7
1 2 2
1 3 8
2 1 -1
2 3 5
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,10 @@
7 9
5 3 14
5 2 31
5 1 0
0 3 40
3 3 22
3 5 10
1 1 42
2 3 28
3 2 5325
@@ -0,0 +1,11 @@
6 10
4 1 26
5 3 14
5 2 31
2 3 28
5 1 0
3 5 10
0 3 40
4 5 10
3 3 22
1 1 42
@@ -0,0 +1,21 @@
7 20
3 3 32
6 0 59
2 3 35
3 5 38
2 5 73
2 1 6
4 2 38
5 3 40
1 5 81
4 4 14
0 6 85
1 1 19
1 2 84
2 0 50
1 0 21
3 6 60
0 4 93
0 5 97
5 6 63
4 5 96
@@ -0,0 +1,41 @@
7 40
1 0 63
6 1 91
3 1 95
3 4 5
3 5 39
0 0 73
1 2 77
5 5 46
1 1 47
6 4 14
5 1 48
0 1 54
0 6 93
4 4 88
0 2 30
0 4 34
6 0 24
3 6 36
0 5 7
4 2 96
5 0 33
4 5 11
4 3 74
3 0 42
5 6 46
1 5 81
4 0 43
5 2 45
2 2 50
2 0 49
5 3 82
1 3 23
6 3 19
2 5 91
6 6 57
2 6 63
2 4 62
2 1 27
1 4 0
4 6 1
@@ -0,0 +1,4 @@
.vscode
*.txt
*.pdf
@@ -0,0 +1,224 @@
#include "directed_graph.h"
#include <unordered_set>
#include <unordered_map>
#include <string>
#include <fstream>
DirectedGraph::DirectedGraph(){
// nothing to do
}
DirectedGraph::~DirectedGraph(){
// nothing to do
}
DirectedGraph::DirectedGraph(const DirectedGraph& g){
this->_vertices = g._vertices;
this->_inbounds.clear();
this->_outbounds.clear();
this->_weights.clear();
for(std::pair<const int, std::unordered_set<int>> p : g._inbounds){
this->_inbounds[p.first] = p.second;
}
for(std::pair<const int, std::unordered_set<int>> p : g._outbounds){
this->_outbounds[p.first] = p.second;
}
for(std::pair<const std::pair<int, int>, int> p : g._weights){
this->_weights[p.first] = p.second;
}
}
DirectedGraph DirectedGraph::operator=(const DirectedGraph& g){
this->_vertices = g._vertices;
this->_inbounds.clear();
this->_outbounds.clear();
this->_weights.clear();
for(std::pair<const int, std::unordered_set<int>> p : g._inbounds){
this->_inbounds[p.first] = p.second;
}
for(std::pair<const int, std::unordered_set<int>> p : g._outbounds){
this->_outbounds[p.first] = p.second;
}
for(std::pair<const std::pair<int, int>, int> p : g._weights){
this->_weights[p.first] = p.second;
}
return *this;
}
DirectedGraph DirectedGraph::reindex() const{
std::unordered_map<int, int> old_to_new;
int i = this->numVertices()-1;
for(int v : this->_vertices){
old_to_new[v] = i;
i--;
}
DirectedGraph new_g;
for(int v : this->_vertices){
new_g.addVertex(old_to_new[v]);
}
for(std::pair<const std::pair<int, int>, int> p : this->_weights){
new_g.addEdge(old_to_new[p.first.first], old_to_new[p.first.second], p.second);
}
return new_g;
}
int DirectedGraph::numVertices() const{
return this->_vertices.size();
}
int DirectedGraph::numEdges() const{
return this->_weights.size();
}
std::unordered_set<int> DirectedGraph::vertices() const{
return this->_vertices;
}
std::unordered_map<std::pair<int, int>, int> DirectedGraph::edges() const{
std::unordered_map<std::pair<int, int>, int> weights;
for(std::pair<const std::pair<int, int>, int> p : this->_weights){
weights[p.first] = p.second;
}
return weights;
}
bool DirectedGraph::isEdge(int v1, int v2) const{
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_weights.find(std::make_pair(v1, v2)) != this->_weights.end();
}
int DirectedGraph::inDegree(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_inbounds.at(v).size();
}
int DirectedGraph::outDegree(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_outbounds.at(v).size();
}
std::unordered_set<int> DirectedGraph::inbounds(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_inbounds.at(v);
}
std::unordered_set<int> DirectedGraph::outbounds(int v) const{
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
return this->_outbounds.at(v);
}
int DirectedGraph::weight(int v1, int v2) const{
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) == this->_weights.end())
throw std::invalid_argument("Edge not found");
return this->_weights.at(std::make_pair(v1, v2));
}
void DirectedGraph::weight(int v1, int v2, int w){
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) == this->_weights.end())
throw std::invalid_argument("Edge not found");
this->_weights[std::make_pair(v1, v2)] = w;
}
void DirectedGraph::addVertex(int v){
if(this->_vertices.find(v) != this->_vertices.end())
throw std::invalid_argument("Vertex already exists");
this->_vertices.insert(v);
this->_inbounds[v] = std::unordered_set<int>();
this->_outbounds[v] = std::unordered_set<int>();
}
void DirectedGraph::removeVertex(int v){
if(this->_vertices.find(v) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
this->_vertices.erase(v);
for(int i : this->_inbounds[v]){
this->_outbounds[i].erase(v);
this->_weights.erase(std::make_pair(i, v));
}
for(int i : this->_outbounds[v]){
this->_inbounds[i].erase(v);
this->_weights.erase(std::make_pair(v, i));
}
this->_inbounds.erase(v);
this->_outbounds.erase(v);
}
void DirectedGraph::addEdge(int v1, int v2, int w){
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) != this->_weights.end())
throw std::invalid_argument("Edge already exists");
this->_weights[std::make_pair(v1, v2)] = w;
this->_inbounds[v2].insert(v1);
this->_outbounds[v1].insert(v2);
}
void DirectedGraph::removeEdge(int v1, int v2){
if(this->_vertices.find(v1) == this->_vertices.end() || this->_vertices.find(v2) == this->_vertices.end())
throw std::invalid_argument("Vertex not found");
if(this->_weights.find(std::make_pair(v1, v2)) == this->_weights.end())
throw std::invalid_argument("Edge not found");
this->_weights.erase(std::make_pair(v1, v2));
this->_inbounds[v2].erase(v1);
this->_outbounds[v1].erase(v2);
}
DirectedGraph read_from_file(std::string filename){
std::ifstream file(filename);
if(!file.is_open())
throw std::invalid_argument("File not found");
DirectedGraph g;
int num_vertices=0;
file >> num_vertices;
for(int i = 0; i < num_vertices; i++){
g.addVertex(i);
}
int num_edges=0;
file >> num_edges;
int v1, v2, w;
for(int i = 0; i < num_edges; i++){
file >> v1 >> v2 >> w;
g.addEdge(v1, v2, w);
}
file.close();
return g;
}
void write_to_file(const DirectedGraph& g, std::string filename){
DirectedGraph new_g = g.reindex();
std::ofstream file(filename);
if(!file.is_open())
throw std::invalid_argument("File could not be opened");
file << new_g.numVertices() << " " << new_g.numEdges() << std::endl;
for(std::pair<const std::pair<int, int>, int> p : new_g.edges()){
file << p.first.first << " " << p.first.second << " " << p.second << std::endl;
}
file.close();
}
DirectedGraph random_graph(int num_vertices, int num_edges){
DirectedGraph g;
for(int i = 0; i < num_vertices; i++){
g.addVertex(i);
}
for(int i = 0; i < num_edges; i++){
int v1 = rand() % num_vertices;
int v2 = rand() % num_vertices;
int w = rand() % 100;
if (g.isEdge(v1, v2)){
i--;
continue;
}
g.addEdge(v1, v2, w);
}
return g;
}
@@ -0,0 +1,47 @@
#pragma once
#include<unordered_set>
#include<unordered_map>
#include<string>
namespace std{
template<>
struct hash<std::pair<int,int>>{
size_t operator()(const std::pair<int,int>& p) const{
return (std::hash<int>()(p.first)<<1) ^ std::hash<int>()(p.second);
}
};
}
class DirectedGraph{
private:
std::unordered_set<int> _vertices;
std::unordered_map<int,std::unordered_set<int>> _inbounds;
std::unordered_map<int,std::unordered_set<int>> _outbounds;
std::unordered_map<std::pair<int,int>,int> _weights;
public:
DirectedGraph();
~DirectedGraph();
DirectedGraph(const DirectedGraph& g);
DirectedGraph operator=(const DirectedGraph& g);
DirectedGraph reindex() const;
int numVertices() const;
int numEdges() const;
std::unordered_set<int> vertices() const;
std::unordered_map<std::pair<int,int>,int> edges() const;
bool isEdge(int v1, int v2) const;
int inDegree(int v) const;
int outDegree(int v) const;
std::unordered_set<int> inbounds(int v) const;
std::unordered_set<int> outbounds(int v) const;
int weight(int v1, int v2) const;
void weight(int v1, int v2, int w);
void addVertex(int v);
void removeVertex(int v);
void addEdge(int v1, int v2, int w);
void removeEdge(int v1, int v2);
};
DirectedGraph read_from_file(std::string filename);
void write_to_file(const DirectedGraph& g, std::string filename);
DirectedGraph random_graph(int num_vertices, int num_edges);
@@ -0,0 +1,12 @@
#include "directed_graph.h"
#include "ui.h"
#include <utility>
#include <vector>
#include <unordered_map>
#include <iostream>
int main(){
UI ui;
ui.run();
return 0;
}
@@ -0,0 +1,282 @@
#include "directed_graph.h"
#include "ui.h"
#include <unordered_set>
#include <unordered_map>
#include <iostream>
UI::UI(){
// nothing to do
}
UI::~UI(){
// nothing to do
}
void UI::run(){
int command;
while(true){
if(this->_graph.numVertices() == 0)
std::cout << std::endl << "Graph is empty" << std::endl;
std::cout << std::endl;
std::cout << "1. Load graph from file" << std::endl;
std::cout << "2. Save graph to file" << std::endl;
std::cout << "3. Generate a graph" << std::endl;
std::cout << "4. Add vertex" << std::endl;
std::cout << "5. Remove vertex" << std::endl;
std::cout << "6. Add edge" << std::endl;
std::cout << "7. Remove edge" << std::endl;
std::cout << "8. Get in degree" << std::endl;
std::cout << "9. Get out degree" << std::endl;
std::cout << "10. Get cost" << std::endl;
std::cout << "11. Set cost" << std::endl;
std::cout << "12. Get number of vertices" << std::endl;
std::cout << "13. Get number of edges" << std::endl;
std::cout << "14. Get vertices" << std::endl;
std::cout << "15. Get edges" << std::endl;
std::cout << "16. Get inbounds" << std::endl;
std::cout << "17. Get outbounds" << std::endl;
std::cout << "18. Get All " << std::endl;
std::cout << "0. Exit" << std::endl;
std::cout << "Command: ";
std::cin >> command;
std::cout << std::endl;
switch(command){
case 1:{
std::string filename;
std::cout << "Filename: ";
std::cin >> filename;
try{
this->_graph = read_from_file(filename);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 2:{
std::string filename;
std::cout << "Filename: ";
std::cin >> filename;
try{
write_to_file(this->_graph, filename);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 3:{
int num_vertices, num_edges;
std::cout << "Number of vertices: ";
std::cin >> num_vertices;
std::cout << "Number of edges: ";
std::cin >> num_edges;
try{
this->_graph = random_graph(num_vertices, num_edges);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 4:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
this->_graph.addVertex(v);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 5:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
this->_graph.removeVertex(v);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 6:{
int v1, v2, w;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
std::cout << "Weight: ";
std::cin >> w;
try{
this->_graph.addEdge(v1, v2, w);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 7:{
int v1, v2;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
try{
this->_graph.removeEdge(v1, v2);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 8:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::cout << "In degree: " << this->_graph.inDegree(v) << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 9:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::cout << "Out degree: " << this->_graph.outDegree(v) << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 10:{
int v1, v2;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
try{
std::cout << "Cost: " << this->_graph.weight(v1, v2) << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 11:{
int v1, v2, w;
std::cout << "Vertex 1: ";
std::cin >> v1;
std::cout << "Vertex 2: ";
std::cin >> v2;
std::cout << "Weight: ";
std::cin >> w;
try{
this->_graph.weight(v1, v2, w);
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 12:{
std::cout << "Number of vertices: " << this->_graph.numVertices() << std::endl;
break;
}
case 13:{
std::cout << "Number of edges: " << this->_graph.numEdges() << std::endl;
break;
}
case 14:{
std::unordered_set<int> vertices = this->_graph.vertices();
for(int vertex : vertices){
std::cout << vertex << " ";
}
std::cout << std::endl;
break;
}
case 15:{
std::unordered_map<std::pair<int, int>, int> edges = this->_graph.edges();
for(std::pair<std::pair<int, int>, int> edge : edges){
std::cout << edge.first.first << " " << edge.first.second << " " << edge.second << std::endl;
}
break;
}
case 16:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::unordered_set<int> inbounds = this->_graph.inbounds(v);
for(int vertex : inbounds){
std::cout << vertex << " ";
}
std::cout << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 17:{
int v;
std::cout << "Vertex: ";
std::cin >> v;
try{
std::unordered_set<int> outbounds = this->_graph.outbounds(v);
for(int vertex : outbounds){
std::cout << vertex << " ";
}
std::cout << std::endl;
}
catch(std::invalid_argument& e){
std::cout << e.what() << std::endl;
}
break;
}
case 18:{
std::cout<<"Inbound: \n";
std::unordered_set<int> vertices = this->_graph.vertices();
for(int vertex : vertices){
std::cout << vertex << ": ";
for(int in : this->_graph.inbounds(vertex)){
std::cout << in << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
vertices = this->_graph.vertices();
std::cout<<"Outbound: \n";
for(int vertex : vertices){
std::cout << vertex << ": ";
for(int out : this->_graph.outbounds(vertex)){
std::cout << out << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
std::cout<<"Edges: \n";
std::unordered_map<std::pair<int, int>, int> edges = this->_graph.edges();
for(std::pair<std::pair<int, int>, int> edge : edges){
std::cout << edge.first.first << " " << edge.first.second << " " << edge.second << std::endl;
}
break;
}
case 0:{
return;
}
default:{
std::cout << "Invalid command" << std::endl;
break;
}
}
}
}
@@ -0,0 +1,11 @@
#pragma once
#include "directed_graph.h"
class UI{
private:
DirectedGraph _graph;
public:
UI();
~UI();
void run();
};
@@ -0,0 +1,243 @@
package DirectedGraphJava;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Queue;
import java.util.Set;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Collections;
public class DirectedGraph implements IDirectedGraph {
private HashSet<Integer> _vertices = new HashSet<Integer>();
private HashMap<Integer, HashSet<Integer>> _inbounds = new HashMap<Integer, HashSet<Integer>>();
private HashMap<Integer, HashSet<Integer>> _outbounds = new HashMap<Integer, HashSet<Integer>>();
private HashMap<Pair<Integer,Integer>,Integer> _edges = new HashMap<Pair<Integer,Integer>,Integer>();
public DirectedGraph() {
//nothing to do
}
public DirectedGraph reindex(){
HashMap<Integer,Integer> oldToNew = new HashMap<Integer,Integer>();
int i = 0;
for (Integer vertex : _vertices) {
oldToNew.put(vertex,i);
i++;
}
DirectedGraph newGraph = new DirectedGraph();
for (Integer vertex : _vertices) {
newGraph.addVertex(oldToNew.get(vertex));
}
for (Pair<Integer,Integer> edge : _edges.keySet()) {
newGraph.addEdge(oldToNew.get(edge.first),oldToNew.get(edge.second),_edges.get(edge));
}
return newGraph;
}
public Integer numVertices() {
return _vertices.size();
}
public Integer numEdges() {
return _edges.size();
}
public Iterator<Integer> vertices() {
return _vertices.iterator();
}
public Iterator<Pair<Pair<Integer,Integer>,Integer>> edges() {
HashSet<Pair<Pair<Integer,Integer>,Integer>> keyValues = new HashSet<Pair<Pair<Integer,Integer>,Integer>>();
for (Pair<Integer,Integer> key : this._edges.keySet()) {
Pair<Pair<Integer,Integer>,Integer> keyValuePair = new Pair<Pair<Integer,Integer>,Integer>(key,this._edges.get(key));
keyValues.add(keyValuePair);
}
return keyValues.iterator();
}
public boolean isEdge(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _edges.containsKey(new Pair<Integer,Integer>(v1,v2));
}
public int inDegree(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _inbounds.get(v).size();
}
public int outDegree(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _outbounds.get(v).size();
}
public Iterator<Integer> inbounds(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _inbounds.get(v).iterator();
}
public Iterator<Integer> outbounds(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _outbounds.get(v).iterator();
}
public Integer weight(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
return _edges.get(new Pair<Integer,Integer>(v1,v2));
}
public void weight(Integer v1, Integer v2, Integer w) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
_edges.put(new Pair<Integer,Integer>(v1,v2),w);
}
public void addVertex(Integer v) {
if(_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex already exists");
}
_vertices.add(v);
_inbounds.put(v,new HashSet<Integer>());
_outbounds.put(v,new HashSet<Integer>());
}
public void removeVertex(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
_vertices.remove(v);
for (Integer vertex : _inbounds.get(v)) {
_outbounds.get(vertex).remove(v);
_edges.remove(new Pair<Integer,Integer>(vertex,v));
}
for (Integer vertex : _outbounds.get(v)) {
_inbounds.get(vertex).remove(v);
_edges.remove(new Pair<Integer,Integer>(v,vertex));
}
_inbounds.remove(v);
_outbounds.remove(v);
}
public void addEdge(Integer v1, Integer v2, Integer w) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge already exists");
}
_edges.put(new Pair<Integer,Integer>(v1,v2),w);
_inbounds.get(v2).add(v1);
_outbounds.get(v1).add(v2);
}
public void removeEdge(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
_edges.remove(new Pair<Integer,Integer>(v1,v2));
_inbounds.get(v2).remove(v1);
_outbounds.get(v1).remove(v2);
}
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v){
//Initializations
Queue<Integer> queue = new LinkedList<Integer>();
HashMap<Integer,Pair<Integer,Integer>> map = new HashMap<Integer,Pair<Integer,Integer>>();
Set<Integer> visited = new HashSet<Integer>();
for(Iterator<Integer> vertex = this._vertices.iterator();vertex.hasNext();){
map.put(vertex.next(),new Pair<Integer,Integer>(null,-1));
}
//Add the first vertex to the queue, the visited set, and the map of distances and parents with a distance of 0
map.put(v,new Pair<Integer,Integer>(null,0));
queue.add(v);
map.put(v,new Pair<Integer,Integer>(null,0));
visited.add(v);
//BFS to find the shortest path
while(!queue.isEmpty()){
Integer current = queue.poll(); //Get the next vertex
//For each neighbor of the current vertex
for(Integer neighbor : _outbounds.get(current)){
//If the neighbor has not been visited, add it to the queue, the visited set, and the map of distances and parents with a distance of 1 more than the current vertex
if(!visited.contains(neighbor)){
queue.add(neighbor);
visited.add(neighbor);
map.put(neighbor,new Pair<Integer,Integer>(current,map.get(current).second+1));
}
}
}
return map;
}
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v,Integer u){
//Initializations
Queue<Integer> queue = new LinkedList<Integer>();
HashMap<Integer,Pair<Integer,Integer>> map = new HashMap<Integer,Pair<Integer,Integer>>();
Set<Integer> visited = new HashSet<Integer>();
for(Iterator<Integer> vertex = this._vertices.iterator();vertex.hasNext();){
map.put(vertex.next(),new Pair<Integer,Integer>(null,-1));
}
//Add the first vertex to the queue, the visited set, and the map of distances and parents with a distance of 0
map.put(v,new Pair<Integer,Integer>(null,0));
queue.add(v);
map.put(v,new Pair<Integer,Integer>(null,0));
visited.add(v);
//BFS to find the shortest path
while(!queue.isEmpty()){
Integer current = queue.poll(); //Get the next vertex
//For each neighbor of the current vertex
for(Integer neighbor : _outbounds.get(current)){
//If the neighbor has not been visited yet add it to the queue, visited set, and map.
if(!visited.contains(neighbor)){
queue.add(neighbor);
visited.add(neighbor);
//Add the neighbor to the map with the current vertex as its parent and a distance of the current vertex's distance + 1
map.put(neighbor,new Pair<Integer,Integer>(current,map.get(current).second+1));
//If the neighbor is the destination vertex return the map
if(neighbor == u)
return map;
}
}
}
return map;
}
public ArrayList<Integer> path(Integer v1,Integer v2){
//Get the shortest path from v1 to v2
HashMap<Integer,Pair<Integer,Integer>> map = shortestPath(v1);
ArrayList<Integer> path = new ArrayList<Integer>();
//If there is no path return an empty arraylist
if(map.get(v2).second == -1)
return path;
path.add(v2);
//Add each vertex in the path to the arraylist starting from the destination vertex
while(map.containsKey(v2)){
path.add(map.get(v2).first);
v2 = map.get(v2).first;
}
//Remove the first element of the arraylist which is null and reverse the arraylist
path.remove(path.size()-1);
Collections.reverse(path);
return path;
}
}
@@ -0,0 +1,27 @@
package DirectedGraphJava;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
interface IDirectedGraph {
public DirectedGraph reindex();
public Integer numVertices();
public Integer numEdges();
public Iterator<Integer> vertices();
public Iterator<Pair<Pair<Integer,Integer>,Integer>> edges();
public boolean isEdge(Integer v1, Integer v2);
public int inDegree(Integer v);
public int outDegree(Integer v);
public Iterator<Integer> inbounds(Integer v);
public Iterator<Integer> outbounds(Integer v);
public Integer weight(Integer v1, Integer v2);
public void weight(Integer v1, Integer v2, Integer w);
public void addVertex(Integer v);
public void removeVertex(Integer v);
public void addEdge(Integer v1, Integer v2, Integer w);
public void removeEdge(Integer v1, Integer v2);
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v);
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v,Integer u);
public ArrayList<Integer> path(Integer v1,Integer v2);
}
@@ -0,0 +1,68 @@
package DirectedGraphJava;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
public class Main {
public static DirectedGraph read_from_file(String filename) throws FileNotFoundException {
DirectedGraph graph = new DirectedGraph();
File file = new File(filename);
Scanner scanner = new Scanner(file);
Integer num_vertices = scanner.nextInt();
for(Integer i = 0; i < num_vertices; i++)
graph.addVertex(i);
Integer num_edges = scanner.nextInt();
for(Integer i = 0; i < num_edges; i++){
Integer v1 = scanner.nextInt();
Integer v2 = scanner.nextInt();
Integer w = scanner.nextInt();
graph.addEdge(v1, v2, w);
}
scanner.close();
return graph;
}
public static void write_to_file(DirectedGraph graph, String filename) throws IOException {
DirectedGraph new_graph = graph.reindex();
File file = new File(filename);
file.createNewFile();
FileWriter writer = new FileWriter(file);
writer.write(new_graph.numVertices().toString() + " " + new_graph.numEdges().toString() + "\n");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = new_graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
writer.write(e.first.first.toString() + " " + e.first.second.toString() + " " + e.second.toString() + "\n");
}
writer.close();
}
public static DirectedGraph random_graph(Integer num_vertices, Integer num_edges) {
DirectedGraph graph = new DirectedGraph();
for(Integer i = 0; i < num_vertices; i++)
graph.addVertex(i);
for(Integer i = 0; i < num_edges; i++){
Integer v1 = (int)(Math.random() * num_vertices);
Integer v2 = (int)(Math.random() * num_vertices);
Integer w = (int)(Math.random() * 100);
if(graph.isEdge(v1, v2)){
i--;
continue;
}
graph.addEdge(v1, v2, w);
}
return graph;
}
public static void main(String[] args) {
ui UI = new ui();
UI.run();
}
}
@@ -0,0 +1,30 @@
package DirectedGraphJava;
public class Pair<T1,T2> {
public T1 first;
public T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair<?, ?> pair = (Pair<?, ?>) o;
if (first != null ? !first.equals(pair.first) : pair.first != null) return false;
return second != null ? second.equals(pair.second) : pair.second == null;
}
@Override
public int hashCode() {
int result = first != null ? first.hashCode() : 0;
result = 31 * result + (second != null ? second.hashCode() : 0);
return result;
}
}
@@ -0,0 +1,304 @@
package DirectedGraphJava;
import java.util.HashMap;
import java.util.Iterator;
public class ui {
private DirectedGraph graph = new DirectedGraph();
public ui(){
}
public void run(){
Integer command;
while(true){
if(this.graph.numVertices() == 0)
System.out.println("Graph is empty");
System.out.println();
System.out.println("1. Load graph from file");
System.out.println("2. Save graph to file");
System.out.println("3. Generate a graph");
System.out.println("4. Add a vertex");
System.out.println("5. Remove a vertex");
System.out.println("6. Add an edge");
System.out.println("7. Remove an edge");
System.out.println("8. Get in degree");
System.out.println("9. Get out degree");
System.out.println("10 Get cost");
System.out.println("11. Set cost");
System.out.println("12. Get number of vertices");
System.out.println("13. Get number of edges");
System.out.println("14. Get vertices");
System.out.println("15. Get edges");
System.out.println("16. Get inbounds");
System.out.println("17. Get outbounds");
System.out.println("18. Get all");
System.out.println("19. Get shortest path to all vertices");
System.out.println("20. Get shortest path to a vertex");
System.out.println("0. Exit");
System.out.print("Command: ");
command = Integer.parseInt(System.console().readLine());
System.out.println();
switch(command){
case 1: {
System.out.print("File name: ");
String fileName = System.console().readLine();
try{
this.graph = Main.read_from_file(fileName);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 2: {
System.out.print("File name: ");
String fileName = System.console().readLine();
try{
Main.write_to_file(this.graph, fileName);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 3: {
System.out.print("Number of vertices: ");
Integer numVertices = Integer.parseInt(System.console().readLine());
System.out.print("Number of edges: ");
Integer numEdges = Integer.parseInt(System.console().readLine());
try{
this.graph = Main.random_graph(numVertices, numEdges);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 4: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
this.graph.addVertex(vertex);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 5: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
this.graph.removeVertex(vertex);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 6: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
System.out.print("Weight: ");
Integer weight = Integer.parseInt(System.console().readLine());
try{
this.graph.addEdge(vertex1, vertex2, weight);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 7: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
try{
this.graph.removeEdge(vertex1, vertex2);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 8: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
System.out.println("In degree: " + this.graph.inDegree(vertex));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 9: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
System.out.println("Out degree: " + this.graph.outDegree(vertex));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 10: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
try{
System.out.println("Cost: " + this.graph.weight(vertex1, vertex2));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 11: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
System.out.print("Weight: ");
Integer weight = Integer.parseInt(System.console().readLine());
try{
this.graph.weight(vertex1, vertex2, weight);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 12: {
System.out.println("Number of vertices: " + this.graph.numVertices());
break;
}
case 13: {
System.out.println("Number of edges: " + this.graph.numEdges());
break;
}
case 14: {
System.out.println("Vertices: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
System.out.println(vertex.next());
}
break;
}
case 15: {
System.out.println("Edges: ");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = this.graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
System.out.println(e.first.first + " " + e.first.second + " " + e.second);
}
break;
}
case 16: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Inbounds: ");
for(Iterator<Integer> inbounds = this.graph.inbounds(vertex); inbounds.hasNext();){
Integer e = inbounds.next();
System.out.println(e);
}
break;
}
case 17: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Outbounds: ");
for(Iterator<Integer> outbounds = this.graph.outbounds(vertex); outbounds.hasNext();){
Integer e = outbounds.next();
System.out.println(e);
}
break;
}
case 18:{
System.out.println("Inbounds: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
Integer v = vertex.next();
System.out.print(v);
System.out.print(": ");
for(Iterator<Integer> inbounds = this.graph.inbounds(v); inbounds.hasNext();){
Integer e = inbounds.next();
System.out.print(e);
System.out.print(" ");
}
System.out.println();
}
System.out.println();
System.out.println("Outbounds: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
Integer v = vertex.next();
System.out.print(v);
System.out.print(": ");
for(Iterator<Integer> outbounds = this.graph.outbounds(v); outbounds.hasNext();){
Integer e = outbounds.next();
System.out.print(e);
System.out.print(" ");
}
System.out.println();
}
System.out.println();
System.out.println("Edges: ");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = this.graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
System.out.println(e.first.first + " " + e.first.second + " " + e.second);
}
break;
}
case 19:{
System.out.println("Enter a vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
HashMap<Integer, Pair<Integer, Integer>> distances = this.graph.shortestPath(vertex);
for(Iterator<Integer> vertex2 = this.graph.vertices(); vertex2.hasNext();){
Integer v = vertex2.next();
System.out.println("Distance from " + vertex + " to " + v + ": " + distances.get(v).second);
System.out.println("Path: ");
if(this.graph.path(vertex, v).isEmpty()){
System.out.println("No path");
continue;
}
for(Iterator<Integer> path = this.graph.path(vertex, v).iterator(); path.hasNext();){
Integer p = path.next();
System.out.print(p);
System.out.print(" ");
}
System.out.println();
}
break;
}
case 20:{
System.out.println("Enter a vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Enter a second vertex: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
HashMap<Integer, Pair<Integer, Integer>> distances = this.graph.shortestPath(vertex, vertex2);
System.out.println("Distance from " + vertex + " to " + vertex2 + ": " + distances.get(vertex2).second);
System.out.println("Path: ");
if(this.graph.path(vertex, vertex2).isEmpty()){
System.out.println("No path");
break;
}
for(Iterator<Integer> path = this.graph.path(vertex, vertex2).iterator(); path.hasNext();){
Integer p = path.next();
System.out.print(p);
System.out.print(" ");
}
System.out.println();
break;
}
case 0:{
System.exit(0);
}
default: {
System.out.println("Invalid option");
break;
}
}
}
}
}
@@ -0,0 +1,4 @@
.vscode
*.txt
*.pdf
@@ -0,0 +1,349 @@
package DirectedGraphJava;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Queue;
import java.util.Set;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Collections;
public class DirectedGraph implements IDirectedGraph {
private HashSet<Integer> _vertices = new HashSet<Integer>();
private HashMap<Integer, HashSet<Integer>> _inbounds = new HashMap<Integer, HashSet<Integer>>();
private HashMap<Integer, HashSet<Integer>> _outbounds = new HashMap<Integer, HashSet<Integer>>();
private HashMap<Pair<Integer,Integer>,Integer> _edges = new HashMap<Pair<Integer,Integer>,Integer>();
public DirectedGraph() {
//nothing to do
}
public DirectedGraph reindex(){
HashMap<Integer,Integer> oldToNew = new HashMap<Integer,Integer>();
int i = 0;
for (Integer vertex : _vertices) {
oldToNew.put(vertex,i);
i++;
}
DirectedGraph newGraph = new DirectedGraph();
for (Integer vertex : _vertices) {
newGraph.addVertex(oldToNew.get(vertex));
}
for (Pair<Integer,Integer> edge : _edges.keySet()) {
newGraph.addEdge(oldToNew.get(edge.first),oldToNew.get(edge.second),_edges.get(edge));
}
return newGraph;
}
public Integer numVertices() {
return _vertices.size();
}
public Integer numEdges() {
return _edges.size();
}
public Iterator<Integer> vertices() {
return _vertices.iterator();
}
public Iterator<Pair<Pair<Integer,Integer>,Integer>> edges() {
HashSet<Pair<Pair<Integer,Integer>,Integer>> keyValues = new HashSet<Pair<Pair<Integer,Integer>,Integer>>();
for (Pair<Integer,Integer> key : this._edges.keySet()) {
Pair<Pair<Integer,Integer>,Integer> keyValuePair = new Pair<Pair<Integer,Integer>,Integer>(key,this._edges.get(key));
keyValues.add(keyValuePair);
}
return keyValues.iterator();
}
public boolean isEdge(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _edges.containsKey(new Pair<Integer,Integer>(v1,v2));
}
public int inDegree(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _inbounds.get(v).size();
}
public int outDegree(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _outbounds.get(v).size();
}
public Iterator<Integer> inbounds(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _inbounds.get(v).iterator();
}
public Iterator<Integer> outbounds(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _outbounds.get(v).iterator();
}
public Integer weight(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
return _edges.get(new Pair<Integer,Integer>(v1,v2));
}
public void weight(Integer v1, Integer v2, Integer w) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
_edges.put(new Pair<Integer,Integer>(v1,v2),w);
}
public void addVertex(Integer v) {
if(_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex already exists");
}
_vertices.add(v);
_inbounds.put(v,new HashSet<Integer>());
_outbounds.put(v,new HashSet<Integer>());
}
public void removeVertex(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
_vertices.remove(v);
for (Integer vertex : _inbounds.get(v)) {
_outbounds.get(vertex).remove(v);
_edges.remove(new Pair<Integer,Integer>(vertex,v));
}
for (Integer vertex : _outbounds.get(v)) {
_inbounds.get(vertex).remove(v);
_edges.remove(new Pair<Integer,Integer>(v,vertex));
}
_inbounds.remove(v);
_outbounds.remove(v);
}
public void addEdge(Integer v1, Integer v2, Integer w) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge already exists");
}
_edges.put(new Pair<Integer,Integer>(v1,v2),w);
_inbounds.get(v2).add(v1);
_outbounds.get(v1).add(v2);
}
public void removeEdge(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
_edges.remove(new Pair<Integer,Integer>(v1,v2));
_inbounds.get(v2).remove(v1);
_outbounds.get(v1).remove(v2);
}
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v){
//Initializations
Queue<Integer> queue = new LinkedList<Integer>();
HashMap<Integer,Pair<Integer,Integer>> map = new HashMap<Integer,Pair<Integer,Integer>>();
Set<Integer> visited = new HashSet<Integer>();
for(Iterator<Integer> vertex = this._vertices.iterator();vertex.hasNext();){
map.put(vertex.next(),new Pair<Integer,Integer>(null,-1));
}
//Add the first vertex to the queue, the visited set, and the map of distances and parents with a distance of 0
map.put(v,new Pair<Integer,Integer>(null,0));
queue.add(v);
map.put(v,new Pair<Integer,Integer>(null,0));
visited.add(v);
//BFS to find the shortest path
while(!queue.isEmpty()){
Integer current = queue.poll(); //Get the next vertex
//For each neighbor of the current vertex
for(Integer neighbor : _outbounds.get(current)){
//If the neighbor has not been visited, add it to the queue, the visited set, and the map of distances and parents with a distance of 1 more than the current vertex
if(!visited.contains(neighbor)){
queue.add(neighbor);
visited.add(neighbor);
map.put(neighbor,new Pair<Integer,Integer>(current,map.get(current).second+1));
}
}
}
return map;
}
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v,Integer u){
//Initializations
Queue<Integer> queue = new LinkedList<Integer>();
HashMap<Integer,Pair<Integer,Integer>> map = new HashMap<Integer,Pair<Integer,Integer>>();
Set<Integer> visited = new HashSet<Integer>();
for(Iterator<Integer> vertex = this._vertices.iterator();vertex.hasNext();){
map.put(vertex.next(),new Pair<Integer,Integer>(null,-1));
}
//Add the first vertex to the queue, the visited set, and the map of distances and parents with a distance of 0
map.put(v,new Pair<Integer,Integer>(null,0));
queue.add(v);
map.put(v,new Pair<Integer,Integer>(null,0));
visited.add(v);
//BFS to find the shortest path
while(!queue.isEmpty()){
Integer current = queue.poll(); //Get the next vertex
//For each neighbor of the current vertex
for(Integer neighbor : _outbounds.get(current)){
//If the neighbor has not been visited yet add it to the queue, visited set, and map.
if(!visited.contains(neighbor)){
queue.add(neighbor);
visited.add(neighbor);
//Add the neighbor to the map with the current vertex as its parent and a distance of the current vertex's distance + 1
map.put(neighbor,new Pair<Integer,Integer>(current,map.get(current).second+1));
//If the neighbor is the destination vertex return the map
if(neighbor == u)
return map;
}
}
}
return map;
}
public ArrayList<Integer> path(Integer v1,Integer v2){
//Get the shortest path from v1 to v2
HashMap<Integer,Pair<Integer,Integer>> map = shortestPath(v1);
ArrayList<Integer> path = new ArrayList<Integer>();
//If there is no path return an empty arraylist
if(map.get(v2).second == -1)
return path;
path.add(v2);
//Add each vertex in the path to the arraylist starting from the destination vertex
while(map.containsKey(v2)){
path.add(map.get(v2).first);
v2 = map.get(v2).first;
}
//Remove the first element of the arraylist which is null and reverse the arraylist
path.remove(path.size()-1);
Collections.reverse(path);
return path;
}
public HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> shortestCost(){
HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> cost_prev_map = new HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>>();
for(Integer i : _vertices){
for(Integer j : _vertices){
if(i==j){
cost_prev_map.put(new Pair<Integer,Integer>(i,j),new Pair<Integer,Integer>(0,null));
}
else if(_edges.containsKey(new Pair<Integer,Integer>(i,j))){
cost_prev_map.put(new Pair<Integer,Integer>(i,j),new Pair<Integer,Integer>(_edges.get(new Pair<Integer,Integer>(i,j)),i));
}
else{
cost_prev_map.put(new Pair<Integer,Integer>(i,j),new Pair<Integer,Integer>(10000,null));
}
}
}
for(Integer k : _vertices){
for(Integer i : _vertices){
for(Integer j : _vertices){
if(cost_prev_map.get(new Pair<Integer,Integer>(i,j)).first > cost_prev_map.get(new Pair<Integer,Integer>(i,k)).first + cost_prev_map.get(new Pair<Integer,Integer>(k,j)).first){
cost_prev_map.put(new Pair<Integer,Integer>(i,j),new Pair<Integer,Integer>(cost_prev_map.get(new Pair<Integer,Integer>(i,k)).first + cost_prev_map.get(new Pair<Integer,Integer>(k,j)).first,cost_prev_map.get(new Pair<Integer,Integer>(k,j)).second));
}
}
}
}
//Check for negative cycles
for(Integer i : _vertices){
if(cost_prev_map.get(new Pair<Integer,Integer>(i,i)).first < 0){
throw new IllegalArgumentException("Graph contains negative cycle");
}
}
return cost_prev_map;
}
public ArrayList<Integer> costPath(Integer v1,Integer v2){
HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> cost_prev_map = shortestCost();
ArrayList<Integer> path = new ArrayList<Integer>();
if(cost_prev_map.get(new Pair<Integer,Integer>(v1,v2)).first == 10000){
return path;
}
path.add(v2);
while(cost_prev_map.get(new Pair<Integer,Integer>(v1,v2)).second != null){
path.add(cost_prev_map.get(new Pair<Integer,Integer>(v1,v2)).second);
v2 = cost_prev_map.get(new Pair<Integer,Integer>(v1,v2)).second;
}
Collections.reverse(path);
return path;
}
public HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> shortestCostDynamic(Integer v1, Integer v2){
HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> cost_prev_map = new HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>>();
//Initialize the map with the first vertex having a distance of 0 and all other vertices having a distance of 10000
for(Integer i : _vertices){
if(i==v1){
cost_prev_map.put(new Pair<Integer,Integer>(i,0),new Pair<Integer,Integer>(0,null));
}
else{
cost_prev_map.put(new Pair<Integer,Integer>(i,0),new Pair<Integer,Integer>(10000,null));
}
}
//For each iteration of k
for(Integer k = 1; k < _vertices.size(); k++){
for(Integer i : _vertices){
for(Integer j : _vertices){
//If the vertex is an edge and the cost of the previous vertex is greater than the current vertex's cost
if(this.isEdge(j,i) && cost_prev_map.get(new Pair<Integer,Integer>(i,k-1)).first > cost_prev_map.get(new Pair<Integer,Integer>(j,k-1)).first + this.weight(j,i)){
//Set the cost of the current vertex to the cost of the previous vertex
cost_prev_map.put(new Pair<Integer,Integer>(i,k),new Pair<Integer,Integer>(cost_prev_map.get(new Pair<Integer,Integer>(j,k-1)).first + this.weight(j,i),j));
}
}
//If the vertex is not an edge and the cost of the previous vertex is greater than the current vertex's cost
if(!cost_prev_map.containsKey(new Pair<Integer,Integer>(i,k))){
//Set the cost of the current vertex to the cost of the previous vertex
cost_prev_map.put(new Pair<Integer,Integer>(i,k),new Pair<Integer,Integer>(cost_prev_map.get(new Pair<Integer,Integer>(i,k-1)).first,cost_prev_map.get(new Pair<Integer,Integer>(i,k-1)).second));
}
}
}
//Check for negative cycles
if(cost_prev_map.get(new Pair<Integer,Integer>(v1,v1)).first < 0){
throw new IllegalArgumentException("Graph contains negative cycle");
}
return cost_prev_map;
}
public ArrayList<Integer> costPathDynamic(Integer v1,Integer v2){
HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> cost_prev_map = shortestCostDynamic(v1,v2);
ArrayList<Integer> path = new ArrayList<Integer>();
//If the cost of the last vertex is 10000(infinity), then there is no path
if(cost_prev_map.get(new Pair<Integer,Integer>(v2,_vertices.size()-1)).first == 10000){
return path;
}
//Add the last vertex to the path
path.add(v2);
Integer k = _vertices.size()-1;
//While the previous vertex is not null (the first vertex), add the previous vertex to the path, and set the current vertex to the previous vertex, and decrement k
while(cost_prev_map.get(new Pair<Integer,Integer>(v2,k)).second != null){
path.add(cost_prev_map.get(new Pair<Integer,Integer>(v2,k)).second);
v2 = cost_prev_map.get(new Pair<Integer,Integer>(v2,k)).second;
k--;
}
Collections.reverse(path);
return path;
}
}
@@ -0,0 +1,29 @@
package DirectedGraphJava;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
interface IDirectedGraph {
public DirectedGraph reindex();
public Integer numVertices();
public Integer numEdges();
public Iterator<Integer> vertices();
public Iterator<Pair<Pair<Integer,Integer>,Integer>> edges();
public boolean isEdge(Integer v1, Integer v2);
public int inDegree(Integer v);
public int outDegree(Integer v);
public Iterator<Integer> inbounds(Integer v);
public Iterator<Integer> outbounds(Integer v);
public Integer weight(Integer v1, Integer v2);
public void weight(Integer v1, Integer v2, Integer w);
public void addVertex(Integer v);
public void removeVertex(Integer v);
public void addEdge(Integer v1, Integer v2, Integer w);
public void removeEdge(Integer v1, Integer v2);
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v);
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v,Integer u);
public HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> shortestCost();
public ArrayList<Integer> path(Integer v1,Integer v2);
public ArrayList<Integer> costPath(Integer v1,Integer v2);
}
@@ -0,0 +1,68 @@
package DirectedGraphJava;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
public class Main {
public static DirectedGraph read_from_file(String filename) throws FileNotFoundException {
DirectedGraph graph = new DirectedGraph();
File file = new File(filename);
Scanner scanner = new Scanner(file);
Integer num_vertices = scanner.nextInt();
for(Integer i = 0; i < num_vertices; i++)
graph.addVertex(i);
Integer num_edges = scanner.nextInt();
for(Integer i = 0; i < num_edges; i++){
Integer v1 = scanner.nextInt();
Integer v2 = scanner.nextInt();
Integer w = scanner.nextInt();
graph.addEdge(v1, v2, w);
}
scanner.close();
return graph;
}
public static void write_to_file(DirectedGraph graph, String filename) throws IOException {
DirectedGraph new_graph = graph.reindex();
File file = new File(filename);
file.createNewFile();
FileWriter writer = new FileWriter(file);
writer.write(new_graph.numVertices().toString() + " " + new_graph.numEdges().toString() + "\n");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = new_graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
writer.write(e.first.first.toString() + " " + e.first.second.toString() + " " + e.second.toString() + "\n");
}
writer.close();
}
public static DirectedGraph random_graph(Integer num_vertices, Integer num_edges) {
DirectedGraph graph = new DirectedGraph();
for(Integer i = 0; i < num_vertices; i++)
graph.addVertex(i);
for(Integer i = 0; i < num_edges; i++){
Integer v1 = (int)(Math.random() * num_vertices);
Integer v2 = (int)(Math.random() * num_vertices);
Integer w = (int)(Math.random() * 100);
if(graph.isEdge(v1, v2)){
i--;
continue;
}
graph.addEdge(v1, v2, w);
}
return graph;
}
public static void main(String[] args) {
ui UI = new ui();
UI.run();
}
}
@@ -0,0 +1,30 @@
package DirectedGraphJava;
public class Pair<T1,T2> {
public T1 first;
public T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair<?, ?> pair = (Pair<?, ?>) o;
if (first != null ? !first.equals(pair.first) : pair.first != null) return false;
return second != null ? second.equals(pair.second) : pair.second == null;
}
@Override
public int hashCode() {
int result = first != null ? first.hashCode() : 0;
result = 31 * result + (second != null ? second.hashCode() : 0);
return result;
}
}
@@ -0,0 +1,330 @@
package DirectedGraphJava;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
public class ui {
private DirectedGraph graph = new DirectedGraph();
public ui(){
}
public void run(){
Integer command;
while(true){
if(this.graph.numVertices() == 0)
System.out.println("Graph is empty");
System.out.println();
System.out.println("1. Load graph from file");
System.out.println("2. Save graph to file");
System.out.println("3. Generate a graph");
System.out.println("4. Add a vertex");
System.out.println("5. Remove a vertex");
System.out.println("6. Add an edge");
System.out.println("7. Remove an edge");
System.out.println("8. Get in degree");
System.out.println("9. Get out degree");
System.out.println("10 Get cost");
System.out.println("11. Set cost");
System.out.println("12. Get number of vertices");
System.out.println("13. Get number of edges");
System.out.println("14. Get vertices");
System.out.println("15. Get edges");
System.out.println("16. Get inbounds");
System.out.println("17. Get outbounds");
System.out.println("18. Get all");
System.out.println("19. Get shortest path to all vertices");
System.out.println("20. Get shortest path to a vertex");
System.out.println("21. Get shortest cost path to a vertex");
System.out.println("0. Exit");
System.out.print("Command: ");
command = Integer.parseInt(System.console().readLine());
System.out.println();
switch(command){
case 1: {
System.out.print("File name: ");
String fileName = System.console().readLine();
try{
this.graph = Main.read_from_file(fileName);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 2: {
System.out.print("File name: ");
String fileName = System.console().readLine();
try{
Main.write_to_file(this.graph, fileName);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 3: {
System.out.print("Number of vertices: ");
Integer numVertices = Integer.parseInt(System.console().readLine());
System.out.print("Number of edges: ");
Integer numEdges = Integer.parseInt(System.console().readLine());
try{
this.graph = Main.random_graph(numVertices, numEdges);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 4: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
this.graph.addVertex(vertex);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 5: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
this.graph.removeVertex(vertex);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 6: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
System.out.print("Weight: ");
Integer weight = Integer.parseInt(System.console().readLine());
try{
this.graph.addEdge(vertex1, vertex2, weight);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 7: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
try{
this.graph.removeEdge(vertex1, vertex2);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 8: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
System.out.println("In degree: " + this.graph.inDegree(vertex));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 9: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
System.out.println("Out degree: " + this.graph.outDegree(vertex));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 10: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
try{
System.out.println("Cost: " + this.graph.weight(vertex1, vertex2));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 11: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
System.out.print("Weight: ");
Integer weight = Integer.parseInt(System.console().readLine());
try{
this.graph.weight(vertex1, vertex2, weight);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 12: {
System.out.println("Number of vertices: " + this.graph.numVertices());
break;
}
case 13: {
System.out.println("Number of edges: " + this.graph.numEdges());
break;
}
case 14: {
System.out.println("Vertices: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
System.out.println(vertex.next());
}
break;
}
case 15: {
System.out.println("Edges: ");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = this.graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
System.out.println(e.first.first + " " + e.first.second + " " + e.second);
}
break;
}
case 16: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Inbounds: ");
for(Iterator<Integer> inbounds = this.graph.inbounds(vertex); inbounds.hasNext();){
Integer e = inbounds.next();
System.out.println(e);
}
break;
}
case 17: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Outbounds: ");
for(Iterator<Integer> outbounds = this.graph.outbounds(vertex); outbounds.hasNext();){
Integer e = outbounds.next();
System.out.println(e);
}
break;
}
case 18:{
System.out.println("Inbounds: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
Integer v = vertex.next();
System.out.print(v);
System.out.print(": ");
for(Iterator<Integer> inbounds = this.graph.inbounds(v); inbounds.hasNext();){
Integer e = inbounds.next();
System.out.print(e);
System.out.print(" ");
}
System.out.println();
}
System.out.println();
System.out.println("Outbounds: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
Integer v = vertex.next();
System.out.print(v);
System.out.print(": ");
for(Iterator<Integer> outbounds = this.graph.outbounds(v); outbounds.hasNext();){
Integer e = outbounds.next();
System.out.print(e);
System.out.print(" ");
}
System.out.println();
}
System.out.println();
System.out.println("Edges: ");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = this.graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
System.out.println(e.first.first + " " + e.first.second + " " + e.second);
}
break;
}
case 19:{
System.out.println("Enter a vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
HashMap<Integer, Pair<Integer, Integer>> distances = this.graph.shortestPath(vertex);
for(Iterator<Integer> vertex2 = this.graph.vertices(); vertex2.hasNext();){
Integer v = vertex2.next();
System.out.println("Distance from " + vertex + " to " + v + ": " + distances.get(v).second);
System.out.println("Path: ");
if(this.graph.path(vertex, v).isEmpty()){
System.out.println("No path");
continue;
}
for(Iterator<Integer> path = this.graph.path(vertex, v).iterator(); path.hasNext();){
Integer p = path.next();
System.out.print(p);
System.out.print(" ");
}
System.out.println();
}
break;
}
case 20:{
System.out.println("Enter a vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Enter a second vertex: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
HashMap<Integer, Pair<Integer, Integer>> distances = this.graph.shortestPath(vertex, vertex2);
System.out.println("Distance from " + vertex + " to " + vertex2 + ": " + distances.get(vertex2).second);
System.out.println("Path: ");
if(this.graph.path(vertex, vertex2).isEmpty()){
System.out.println("No path");
break;
}
for(Iterator<Integer> path = this.graph.path(vertex, vertex2).iterator(); path.hasNext();){
Integer p = path.next();
System.out.print(p);
System.out.print(" ");
}
System.out.println();
break;
}
case 21:{
System.out.println("Enter a vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Enter a second vertex: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
ArrayList<Integer> path = this.graph.costPathDynamic(vertex, vertex2);
if(path.isEmpty()){
System.out.println("No path");
break;
}
System.out.println("Path: ");
for(Iterator<Integer> p = path.iterator(); p.hasNext();){
Integer v = p.next();
System.out.print(v);
System.out.print(" ");
}
Integer cost = 0;
for(Integer i=0; i<path.size()-1; i++){
cost += this.graph.weight(path.get(i), path.get(i+1));
}
System.out.println();
System.out.println("Cost: " + cost);
break;
}
case 0:{
System.exit(0);
}
default: {
System.out.println("Invalid option");
break;
}
}
}
}
}
@@ -0,0 +1,4 @@
.vscode
*.txt
*.pdf
@@ -0,0 +1,378 @@
package DirectedGraphJava;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Queue;
import java.util.Set;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Stack;
import javax.swing.event.InternalFrameAdapter;
public class DirectedGraph implements IDirectedGraph {
private HashSet<Integer> _vertices = new HashSet<Integer>();
private HashMap<Integer, HashSet<Integer>> _inbounds = new HashMap<Integer, HashSet<Integer>>();
private HashMap<Integer, HashSet<Integer>> _outbounds = new HashMap<Integer, HashSet<Integer>>();
private HashMap<Pair<Integer,Integer>,Integer> _edges = new HashMap<Pair<Integer,Integer>,Integer>();
public DirectedGraph() {
//nothing to do
}
public DirectedGraph reindex(){
HashMap<Integer,Integer> oldToNew = new HashMap<Integer,Integer>();
int i = 0;
for (Integer vertex : _vertices) {
oldToNew.put(vertex,i);
i++;
}
DirectedGraph newGraph = new DirectedGraph();
for (Integer vertex : _vertices) {
newGraph.addVertex(oldToNew.get(vertex));
}
for (Pair<Integer,Integer> edge : _edges.keySet()) {
newGraph.addEdge(oldToNew.get(edge.first),oldToNew.get(edge.second),_edges.get(edge));
}
return newGraph;
}
public Integer numVertices() {
return _vertices.size();
}
public Integer numEdges() {
return _edges.size();
}
public Iterator<Integer> vertices() {
return _vertices.iterator();
}
public Iterator<Pair<Pair<Integer,Integer>,Integer>> edges() {
HashSet<Pair<Pair<Integer,Integer>,Integer>> keyValues = new HashSet<Pair<Pair<Integer,Integer>,Integer>>();
for (Pair<Integer,Integer> key : this._edges.keySet()) {
Pair<Pair<Integer,Integer>,Integer> keyValuePair = new Pair<Pair<Integer,Integer>,Integer>(key,this._edges.get(key));
keyValues.add(keyValuePair);
}
return keyValues.iterator();
}
public boolean isEdge(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _edges.containsKey(new Pair<Integer,Integer>(v1,v2));
}
public int inDegree(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _inbounds.get(v).size();
}
public int outDegree(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _outbounds.get(v).size();
}
public Iterator<Integer> inbounds(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _inbounds.get(v).iterator();
}
public Iterator<Integer> outbounds(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
return _outbounds.get(v).iterator();
}
public Integer weight(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
return _edges.get(new Pair<Integer,Integer>(v1,v2));
}
public void weight(Integer v1, Integer v2, Integer w) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
_edges.put(new Pair<Integer,Integer>(v1,v2),w);
}
public void addVertex(Integer v) {
if(_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex already exists");
}
_vertices.add(v);
_inbounds.put(v,new HashSet<Integer>());
_outbounds.put(v,new HashSet<Integer>());
}
public void removeVertex(Integer v) {
if(!_vertices.contains(v)) {
throw new IllegalArgumentException("Vertex does not exist");
}
_vertices.remove(v);
for (Integer vertex : _inbounds.get(v)) {
_outbounds.get(vertex).remove(v);
_edges.remove(new Pair<Integer,Integer>(vertex,v));
}
for (Integer vertex : _outbounds.get(v)) {
_inbounds.get(vertex).remove(v);
_edges.remove(new Pair<Integer,Integer>(v,vertex));
}
_inbounds.remove(v);
_outbounds.remove(v);
}
public void addEdge(Integer v1, Integer v2, Integer w) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge already exists");
}
_edges.put(new Pair<Integer,Integer>(v1,v2),w);
_inbounds.get(v2).add(v1);
_outbounds.get(v1).add(v2);
}
public void removeEdge(Integer v1, Integer v2) {
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
throw new IllegalArgumentException("Vertex does not exist");
}
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
throw new IllegalArgumentException("Edge does not exist");
}
_edges.remove(new Pair<Integer,Integer>(v1,v2));
_inbounds.get(v2).remove(v1);
_outbounds.get(v1).remove(v2);
}
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v){
//Initializations
Queue<Integer> queue = new LinkedList<Integer>();
HashMap<Integer,Pair<Integer,Integer>> map = new HashMap<Integer,Pair<Integer,Integer>>();
Set<Integer> visited = new HashSet<Integer>();
for(Iterator<Integer> vertex = this._vertices.iterator();vertex.hasNext();){
map.put(vertex.next(),new Pair<Integer,Integer>(null,-1));
}
//Add the first vertex to the queue, the visited set, and the map of distances and parents with a distance of 0
map.put(v,new Pair<Integer,Integer>(null,0));
queue.add(v);
map.put(v,new Pair<Integer,Integer>(null,0));
visited.add(v);
//BFS to find the shortest path
while(!queue.isEmpty()){
Integer current = queue.poll(); //Get the next vertex
//For each neighbor of the current vertex
for(Integer neighbor : _outbounds.get(current)){
//If the neighbor has not been visited, add it to the queue, the visited set, and the map of distances and parents with a distance of 1 more than the current vertex
if(!visited.contains(neighbor)){
queue.add(neighbor);
visited.add(neighbor);
map.put(neighbor,new Pair<Integer,Integer>(current,map.get(current).second+1));
}
}
}
return map;
}
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v,Integer u){
//Initializations
Queue<Integer> queue = new LinkedList<Integer>();
HashMap<Integer,Pair<Integer,Integer>> map = new HashMap<Integer,Pair<Integer,Integer>>();
Set<Integer> visited = new HashSet<Integer>();
for(Iterator<Integer> vertex = this._vertices.iterator();vertex.hasNext();){
map.put(vertex.next(),new Pair<Integer,Integer>(null,-1));
}
//Add the first vertex to the queue, the visited set, and the map of distances and parents with a distance of 0
map.put(v,new Pair<Integer,Integer>(null,0));
queue.add(v);
map.put(v,new Pair<Integer,Integer>(null,0));
visited.add(v);
//BFS to find the shortest path
while(!queue.isEmpty()){
Integer current = queue.poll(); //Get the next vertex
//For each neighbor of the current vertex
for(Integer neighbor : _outbounds.get(current)){
//If the neighbor has not been visited yet add it to the queue, visited set, and map.
if(!visited.contains(neighbor)){
queue.add(neighbor);
visited.add(neighbor);
//Add the neighbor to the map with the current vertex as its parent and a distance of the current vertex's distance + 1
map.put(neighbor,new Pair<Integer,Integer>(current,map.get(current).second+1));
//If the neighbor is the destination vertex return the map
if(neighbor == u)
return map;
}
}
}
return map;
}
public ArrayList<Integer> path(Integer v1,Integer v2){
//Get the shortest path from v1 to v2
HashMap<Integer,Pair<Integer,Integer>> map = shortestPath(v1);
ArrayList<Integer> path = new ArrayList<Integer>();
//If there is no path return an empty arraylist
if(map.get(v2).second == -1)
return path;
path.add(v2);
//Add each vertex in the path to the arraylist starting from the destination vertex
while(map.containsKey(v2)){
path.add(map.get(v2).first);
v2 = map.get(v2).first;
}
//Remove the first element of the arraylist which is null and reverse the arraylist
path.remove(path.size()-1);
Collections.reverse(path);
return path;
}
public HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> shortestCostDynamic(Integer v1, Integer v2){
HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> cost_prev_map = new HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>>();
//Initialize the map with the first vertex having a distance of 0 and all other vertices having a distance of 10000
for(Integer i : _vertices){
if(i==v1){
cost_prev_map.put(new Pair<Integer,Integer>(i,0),new Pair<Integer,Integer>(0,null));
}
else{
cost_prev_map.put(new Pair<Integer,Integer>(i,0),new Pair<Integer,Integer>(10000,null));
}
}
//For each iteration of k
for(Integer k = 1; k < _vertices.size(); k++){
for(Integer i : _vertices){
for(Integer j : _vertices){
//If the vertex is an edge and the cost of the previous vertex is greater than the current vertex's cost
if(this.isEdge(j,i) && cost_prev_map.get(new Pair<Integer,Integer>(i,k-1)).first > cost_prev_map.get(new Pair<Integer,Integer>(j,k-1)).first + this.weight(j,i)){
//Set the cost of the current vertex to the cost of the previous vertex
cost_prev_map.put(new Pair<Integer,Integer>(i,k),new Pair<Integer,Integer>(cost_prev_map.get(new Pair<Integer,Integer>(j,k-1)).first + this.weight(j,i),j));
}
}
//If the vertex is not an edge and the cost of the previous vertex is greater than the current vertex's cost
if(!cost_prev_map.containsKey(new Pair<Integer,Integer>(i,k))){
//Set the cost of the current vertex to the cost of the previous vertex
cost_prev_map.put(new Pair<Integer,Integer>(i,k),new Pair<Integer,Integer>(cost_prev_map.get(new Pair<Integer,Integer>(i,k-1)).first,cost_prev_map.get(new Pair<Integer,Integer>(i,k-1)).second));
}
}
}
//Check for negative cycles
if(cost_prev_map.get(new Pair<Integer,Integer>(v1,v1)).first < 0){
throw new IllegalArgumentException("Graph contains negative cycle");
}
return cost_prev_map;
}
public ArrayList<Integer> costPathDynamic(Integer v1,Integer v2){
HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> cost_prev_map = shortestCostDynamic(v1,v2);
ArrayList<Integer> path = new ArrayList<Integer>();
//If the cost of the last vertex is 10000(infinity), then there is no path
if(cost_prev_map.get(new Pair<Integer,Integer>(v2,_vertices.size()-1)).first == 10000){
return path;
}
//Add the last vertex to the path
path.add(v2);
Integer k = _vertices.size()-1;
//While the previous vertex is not null (the first vertex), add the previous vertex to the path, and set the current vertex to the previous vertex, and decrement k
while(cost_prev_map.get(new Pair<Integer,Integer>(v2,k)).second != null){
path.add(cost_prev_map.get(new Pair<Integer,Integer>(v2,k)).second);
v2 = cost_prev_map.get(new Pair<Integer,Integer>(v2,k)).second;
k--;
}
Collections.reverse(path);
return path;
}
public Boolean TopoSortDFS(Integer x, ArrayList<Integer> sorted , Set<Integer> fullyProcessd, Set<Integer> inProcess){
// If the vertex is in the inProcess set, then there is a cycle
inProcess.add(x);
// For each outbound vertex
for(Integer y : _inbounds.get(x)){
// If the vertex is in the inProcess set, then there is a cycle
if(inProcess.contains(y)){
return false;
}
// If the vertex is not in the fullyProcessd set, then recursively call the function
else if(!fullyProcessd.contains(y)){
if(!TopoSortDFS(y,sorted,fullyProcessd,inProcess)){
return false;
}
}
}
inProcess.remove(x);
fullyProcessd.add(x);
sorted.add(x);
return true;
}
public ArrayList<Integer> TopoSort(){
ArrayList<Integer> sorted = new ArrayList<Integer>();
Set<Integer> fullyProcessd = new HashSet<Integer>();
Set<Integer> inProcess = new HashSet<Integer>();
// For each vertex
for(Integer x : _vertices){
// If the vertex is not in the fullyProcessd set, then recursively call the function
if(!fullyProcessd.contains(x)){
if(!TopoSortDFS(x,sorted,fullyProcessd,inProcess)){
return null;
}
}
}
return sorted;
}
public ArrayList<Integer> highestCostPathDAG(Integer v1, Integer v2){
ArrayList<Integer> sorted = TopoSort();
if(sorted == null){
return null;
}
// Initialize the distance and previous vertex maps
HashMap<Integer,Integer> dist = new HashMap<Integer,Integer>();
HashMap<Integer,Integer> prev = new HashMap<Integer,Integer>();
for(Integer i : _vertices){
dist.put(i,-10000);
prev.put(i,null);
}
dist.put(v1,0);
// For each vertex in the sorted list
while(!sorted.isEmpty()){
// Remove the vertex from the sorted list
Integer u = sorted.remove(0);
if(dist.get(u) != -10000){
for(Integer v : _outbounds.get(u)){
// If the distance of the current vertex is less than the distance of the previous vertex plus the weight of the edge, then set the distance of the current vertex to the distance of the previous vertex plus the weight of the edge, and set the previous vertex of the current vertex to the previous vertex
if(dist.get(v) < dist.get(u) + this.weight(u,v)){
dist.put(v,dist.get(u) + this.weight(u,v));
prev.put(v,u);
}
}
}
}
ArrayList<Integer> path = new ArrayList<Integer>();
Integer u = v2;
while(u != null){
path.add(u);
u = prev.get(u);
}
Collections.reverse(path);
return path;
}
}
@@ -0,0 +1,30 @@
package DirectedGraphJava;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
interface IDirectedGraph {
public DirectedGraph reindex();
public Integer numVertices();
public Integer numEdges();
public Iterator<Integer> vertices();
public Iterator<Pair<Pair<Integer,Integer>,Integer>> edges();
public boolean isEdge(Integer v1, Integer v2);
public int inDegree(Integer v);
public int outDegree(Integer v);
public Iterator<Integer> inbounds(Integer v);
public Iterator<Integer> outbounds(Integer v);
public Integer weight(Integer v1, Integer v2);
public void weight(Integer v1, Integer v2, Integer w);
public void addVertex(Integer v);
public void removeVertex(Integer v);
public void addEdge(Integer v1, Integer v2, Integer w);
public void removeEdge(Integer v1, Integer v2);
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v);
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v,Integer u);
public HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> shortestCostDynamic(Integer v1, Integer v2);
public ArrayList<Integer> path(Integer v1,Integer v2);
public ArrayList<Integer> costPathDynamic(Integer v1,Integer v2);
}
@@ -0,0 +1,68 @@
package DirectedGraphJava;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
public class Main {
public static DirectedGraph read_from_file(String filename) throws FileNotFoundException {
DirectedGraph graph = new DirectedGraph();
File file = new File(filename);
Scanner scanner = new Scanner(file);
Integer num_vertices = scanner.nextInt();
for(Integer i = 0; i < num_vertices; i++)
graph.addVertex(i);
Integer num_edges = scanner.nextInt();
for(Integer i = 0; i < num_edges; i++){
Integer v1 = scanner.nextInt();
Integer v2 = scanner.nextInt();
Integer w = scanner.nextInt();
graph.addEdge(v1, v2, w);
}
scanner.close();
return graph;
}
public static void write_to_file(DirectedGraph graph, String filename) throws IOException {
DirectedGraph new_graph = graph.reindex();
File file = new File(filename);
file.createNewFile();
FileWriter writer = new FileWriter(file);
writer.write(new_graph.numVertices().toString() + " " + new_graph.numEdges().toString() + "\n");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = new_graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
writer.write(e.first.first.toString() + " " + e.first.second.toString() + " " + e.second.toString() + "\n");
}
writer.close();
}
public static DirectedGraph random_graph(Integer num_vertices, Integer num_edges) {
DirectedGraph graph = new DirectedGraph();
for(Integer i = 0; i < num_vertices; i++)
graph.addVertex(i);
for(Integer i = 0; i < num_edges; i++){
Integer v1 = (int)(Math.random() * num_vertices);
Integer v2 = (int)(Math.random() * num_vertices);
Integer w = (int)(Math.random() * 100);
if(graph.isEdge(v1, v2)){
i--;
continue;
}
graph.addEdge(v1, v2, w);
}
return graph;
}
public static void main(String[] args) {
ui UI = new ui();
UI.run();
}
}
@@ -0,0 +1,30 @@
package DirectedGraphJava;
public class Pair<T1,T2> {
public T1 first;
public T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair<?, ?> pair = (Pair<?, ?>) o;
if (first != null ? !first.equals(pair.first) : pair.first != null) return false;
return second != null ? second.equals(pair.second) : pair.second == null;
}
@Override
public int hashCode() {
int result = first != null ? first.hashCode() : 0;
result = 31 * result + (second != null ? second.hashCode() : 0);
return result;
}
}
@@ -0,0 +1,372 @@
package DirectedGraphJava;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
public class ui {
private DirectedGraph graph = new DirectedGraph();
public ui(){
}
public void run(){
Integer command;
while(true){
if(this.graph.numVertices() == 0)
System.out.println("Graph is empty");
System.out.println();
System.out.println("1. Load graph from file");
System.out.println("2. Save graph to file");
System.out.println("3. Generate a graph");
System.out.println("4. Add a vertex");
System.out.println("5. Remove a vertex");
System.out.println("6. Add an edge");
System.out.println("7. Remove an edge");
System.out.println("8. Get in degree");
System.out.println("9. Get out degree");
System.out.println("10 Get cost");
System.out.println("11. Set cost");
System.out.println("12. Get number of vertices");
System.out.println("13. Get number of edges");
System.out.println("14. Get vertices");
System.out.println("15. Get edges");
System.out.println("16. Get inbounds");
System.out.println("17. Get outbounds");
System.out.println("18. Get all");
System.out.println("19. Get shortest path to all vertices");
System.out.println("20. Get shortest path to a vertex");
System.out.println("21. Get shortest cost path to a vertex");
System.out.println("22. Get topological sort");
System.out.println("23. Get highest cost path to a vertex");
System.out.println("0. Exit");
System.out.print("Command: ");
command = Integer.parseInt(System.console().readLine());
System.out.println();
switch(command){
case 1: {
System.out.print("File name: ");
String fileName = System.console().readLine();
try{
this.graph = Main.read_from_file(fileName);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 2: {
System.out.print("File name: ");
String fileName = System.console().readLine();
try{
Main.write_to_file(this.graph, fileName);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 3: {
System.out.print("Number of vertices: ");
Integer numVertices = Integer.parseInt(System.console().readLine());
System.out.print("Number of edges: ");
Integer numEdges = Integer.parseInt(System.console().readLine());
try{
this.graph = Main.random_graph(numVertices, numEdges);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 4: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
this.graph.addVertex(vertex);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 5: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
this.graph.removeVertex(vertex);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 6: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
System.out.print("Weight: ");
Integer weight = Integer.parseInt(System.console().readLine());
try{
this.graph.addEdge(vertex1, vertex2, weight);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 7: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
try{
this.graph.removeEdge(vertex1, vertex2);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 8: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
System.out.println("In degree: " + this.graph.inDegree(vertex));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 9: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
try{
System.out.println("Out degree: " + this.graph.outDegree(vertex));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 10: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
try{
System.out.println("Cost: " + this.graph.weight(vertex1, vertex2));
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 11: {
System.out.print("Vertex 1: ");
Integer vertex1 = Integer.parseInt(System.console().readLine());
System.out.print("Vertex 2: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
System.out.print("Weight: ");
Integer weight = Integer.parseInt(System.console().readLine());
try{
this.graph.weight(vertex1, vertex2, weight);
}
catch(Exception e){
System.out.println("Error: " + e.getMessage());
}
break;
}
case 12: {
System.out.println("Number of vertices: " + this.graph.numVertices());
break;
}
case 13: {
System.out.println("Number of edges: " + this.graph.numEdges());
break;
}
case 14: {
System.out.println("Vertices: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
System.out.println(vertex.next());
}
break;
}
case 15: {
System.out.println("Edges: ");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = this.graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
System.out.println(e.first.first + " " + e.first.second + " " + e.second);
}
break;
}
case 16: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Inbounds: ");
for(Iterator<Integer> inbounds = this.graph.inbounds(vertex); inbounds.hasNext();){
Integer e = inbounds.next();
System.out.println(e);
}
break;
}
case 17: {
System.out.print("Vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Outbounds: ");
for(Iterator<Integer> outbounds = this.graph.outbounds(vertex); outbounds.hasNext();){
Integer e = outbounds.next();
System.out.println(e);
}
break;
}
case 18:{
System.out.println("Inbounds: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
Integer v = vertex.next();
System.out.print(v);
System.out.print(": ");
for(Iterator<Integer> inbounds = this.graph.inbounds(v); inbounds.hasNext();){
Integer e = inbounds.next();
System.out.print(e);
System.out.print(" ");
}
System.out.println();
}
System.out.println();
System.out.println("Outbounds: ");
for(Iterator<Integer> vertex = this.graph.vertices(); vertex.hasNext();){
Integer v = vertex.next();
System.out.print(v);
System.out.print(": ");
for(Iterator<Integer> outbounds = this.graph.outbounds(v); outbounds.hasNext();){
Integer e = outbounds.next();
System.out.print(e);
System.out.print(" ");
}
System.out.println();
}
System.out.println();
System.out.println("Edges: ");
for(Iterator<Pair<Pair<Integer, Integer>,Integer>> edge = this.graph.edges(); edge.hasNext();){
Pair<Pair<Integer, Integer>,Integer> e = edge.next();
System.out.println(e.first.first + " " + e.first.second + " " + e.second);
}
break;
}
case 19:{
System.out.println("Enter a vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
HashMap<Integer, Pair<Integer, Integer>> distances = this.graph.shortestPath(vertex);
for(Iterator<Integer> vertex2 = this.graph.vertices(); vertex2.hasNext();){
Integer v = vertex2.next();
System.out.println("Distance from " + vertex + " to " + v + ": " + distances.get(v).second);
System.out.println("Path: ");
if(this.graph.path(vertex, v).isEmpty()){
System.out.println("No path");
continue;
}
for(Iterator<Integer> path = this.graph.path(vertex, v).iterator(); path.hasNext();){
Integer p = path.next();
System.out.print(p);
System.out.print(" ");
}
System.out.println();
}
break;
}
case 20:{
System.out.println("Enter a vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Enter a second vertex: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
HashMap<Integer, Pair<Integer, Integer>> distances = this.graph.shortestPath(vertex, vertex2);
System.out.println("Distance from " + vertex + " to " + vertex2 + ": " + distances.get(vertex2).second);
System.out.println("Path: ");
if(this.graph.path(vertex, vertex2).isEmpty()){
System.out.println("No path");
break;
}
for(Iterator<Integer> path = this.graph.path(vertex, vertex2).iterator(); path.hasNext();){
Integer p = path.next();
System.out.print(p);
System.out.print(" ");
}
System.out.println();
break;
}
case 21:{
System.out.println("Enter a vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Enter a second vertex: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
ArrayList<Integer> path = this.graph.costPathDynamic(vertex, vertex2);
if(path.isEmpty()){
System.out.println("No path");
break;
}
System.out.println("Path: ");
for(Iterator<Integer> p = path.iterator(); p.hasNext();){
Integer v = p.next();
System.out.print(v);
System.out.print(" ");
}
Integer cost = 0;
for(Integer i=0; i<path.size()-1; i++){
cost += this.graph.weight(path.get(i), path.get(i+1));
}
System.out.println();
System.out.println("Cost: " + cost);
break;
}
case 22:{
ArrayList<Integer> topologicSort = this.graph.TopoSort();
if(topologicSort == null){
System.out.println("Graph is not a DAG");
break;
}
System.out.println("Topological Sort: ");
for(Iterator<Integer> vertex = topologicSort.iterator(); vertex.hasNext();){
Integer v = vertex.next();
System.out.print(v);
System.out.print(" ");
}
System.out.println();
break;
}
case 23:{
System.out.println("Enter a vertex: ");
Integer vertex = Integer.parseInt(System.console().readLine());
System.out.println("Enter a second vertex: ");
Integer vertex2 = Integer.parseInt(System.console().readLine());
ArrayList<Integer> path = this.graph.highestCostPathDAG(vertex, vertex2);
if(path == null || path.isEmpty()){
System.out.println("No path");
break;
}
System.out.println("Path: ");
for(Iterator<Integer> p = path.iterator(); p.hasNext();){
Integer v = p.next();
System.out.print(v);
System.out.print(" ");
}
Integer cost = 0;
for(Integer i=0; i<path.size()-1; i++){
cost += this.graph.weight(path.get(i), path.get(i+1));
}
System.out.println();
System.out.println("Cost: " + cost);
break;
}
case 0:{
System.exit(0);
}
default: {
System.out.println("Invalid option");
break;
}
}
}
}
}
@@ -0,0 +1,41 @@
class Graph:
def __init__(self,n:int):
'''
Constructs a graph with n vertices numbered from 0 to n-1 and no edges.
'''
pass
def addEdge(self,x,y):
'''
Adds an edge from x to y. Returns True on success, False if the edge already exists. Precond: x and y exists
'''
pass
def parseX(self):
pass
def parseNOut(self,x):
pass
def parseNIn(self,x):
pass
def isEdge(self,x,y):
pass
def print_graph(g:Graph):
print("Outbound")
for x in g.parseX():
print(x,":",end="")
for y in g.parseNOut(x):
print(y," ",end="")
print()
def create_small_graph():
g=Graph(3)
for e in [(0,0),(0,1),(0.2)]:
g.addEdge(e[0],e[1])
return g
def main():
g=create_small_graph()
print_graph(g)
@@ -0,0 +1,41 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
x64
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
*.sln
*.ui
*.qrc
.vs
@@ -0,0 +1,108 @@
#include "Admin_view.h"
#include "Service.h"
#include <qheaderview.h>
#include<QObject>
#include <QMessageBox>
#include <algorithm>
Admin_view::Admin_view(Service& subject, User& user, QWidget* parent) : _subject{subject} , _user{user}, QWidget{parent}
{
_subject.attach(this);
_combo = new QComboBox{};
_combo->addItems(QStringList{QString::fromStdString("All"), QString::fromStdString("Wood"), QString::fromStdString("Artifacts"), QString::fromStdString("Painting")});
_combo->setCurrentIndex(0);
_table = new QTableWidget{1, 3};
_table->setHorizontalHeaderLabels(QStringList{"Name", "Category", "Current price"});
_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
populate_table();
QVBoxLayout* layout = new QVBoxLayout{};
layout->addWidget(_combo);
layout->addWidget(_table);
_name = new QLineEdit{};
_category = new QLineEdit{};
_price = new QLineEdit{};
_validator = new QIntValidator();
_validator->setBottom(0);
_price->setValidator(_validator);
_add_button = new QPushButton{"Add"};
layout->addWidget(_name);
layout->addWidget(_category);
layout->addWidget(_price);
layout->addWidget(_add_button);
_table_item = new QTableWidget{1, 3};
_table_item->setHorizontalHeaderLabels(QStringList{"User Id", "Date", "Offer"});
_table_item->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
layout->addWidget(_table_item);
setLayout(layout);
this->setWindowTitle(QString::fromStdString(_user.name()));
QObject::connect(_add_button, &QPushButton::clicked, [&]() {
std::string name = _name->text().toStdString();
std::string category = _category->text().toStdString();
int price = _price->text().toInt();
if (name == "" || category == "" || price == 0)
{
QMessageBox::critical(this, "Error", "Invalid input");
return;
}
try
{
_subject.add(name, category, price);
}
catch (std::exception& e)
{
QMessageBox::critical(this, "Error", e.what());
}
});
QObject::connect(_combo, &QComboBox::currentTextChanged, this, &Admin_view::populate_table);
QObject::connect(_table, &QTableWidget::itemSelectionChanged, this, &Admin_view::populate_table_item);
}
void Admin_view::update()
{
populate_table();
}
void Admin_view::populate_table()
{
std::string _category = _combo->currentText().toStdString();
_table->setRowCount(0);
std::vector<Item> items = _subject.get_items();
std::sort(items.begin(), items.end(), [](const Item& a, const Item& b) {return a.price() < b.price(); });
for (auto item : items)
{
if(_category == "All" || _category == item.category())
{
int row = _table->rowCount();
_table->insertRow(row);
_table->setItem(row, 0, new QTableWidgetItem{QString::fromStdString(item.name())});
_table->setItem(row, 1, new QTableWidgetItem{QString::fromStdString(item.category())});
_table->setItem(row, 2, new QTableWidgetItem{QString::number(item.price())});
}
}
}
void Admin_view::populate_table_item(){
//QMessageBox::critical(this, "Error", "Invalid input");
QModelIndexList selection = _table->selectionModel()->selectedIndexes();
if (selection.isEmpty())
{
_table_item->setRowCount(0);
return;
}
int row = selection.at(0).row();
std::string name = _table->item(row, 0)->text().toStdString();
Item item = _subject.find_item(name);
_table_item->setRowCount(0);
auto offers = item.offers();
std::sort(offers.begin(), offers.end(), [](const auto& a, const auto& b) {return std::get<1>(a) > std::get<1>(b); });
for( auto offer : offers){
int row = _table_item->rowCount();
_table_item->insertRow(row);
_table_item->setItem(row, 0, new QTableWidgetItem{QString::number(std::get<0>(offer))});
_table_item->setItem(row, 1, new QTableWidgetItem{QString::fromStdString(std::get<1>(offer))});
_table_item->setItem(row, 2, new QTableWidgetItem{QString::number(std::get<2>(offer))});
}
}
@@ -0,0 +1,35 @@
#pragma once
#include <QWidget>
#include <QTableWidget>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QIntValidator>
#include <QComboBox>
#include "Subject.h"
#include "Service.h"
class Admin_view : public QWidget , virtual public Observer
{
private:
Service& _subject;
QComboBox* _combo;
QTableWidget* _table;
QLineEdit* _name;
QLineEdit* _category;
QLineEdit* _price;
QPushButton* _add_button;
QIntValidator* _validator;
QTableWidget* _table_item;
User& _user;
public:
Admin_view(Service& subject, User& user, QWidget* parent = nullptr);
void update() override;
void populate_table();
void populate_table_item();
};
@@ -0,0 +1,107 @@
#include "Collector_view.h"
#include "Service.h"
#include <qheaderview.h>
#include <algorithm>
#include <QModelIndex>
#include <tuple>
#include <QMessageBox>
Collector_view::Collector_view(Service& subject, User& user, QWidget* parent) : _subject{subject} , _user{user}, QWidget{parent}
{
_subject.attach(this);
_combo = new QComboBox{};
_combo->addItems(QStringList{QString::fromStdString("All"), QString::fromStdString("Wood"), QString::fromStdString("Artifacts"), QString::fromStdString("Painting")});
_combo->setCurrentIndex(0);
_table = new QTableWidget{1, 3};
_table->setHorizontalHeaderLabels(QStringList{"Name", "Category", "Current price"});
_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
populate_table();
QVBoxLayout* layout = new QVBoxLayout{};
layout->addWidget(_combo);
layout->addWidget(_table);
_table_item = new QTableWidget{1, 3};
_table_item->setHorizontalHeaderLabels(QStringList{"User Id", "Date", "Offer"});
_table_item->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
layout->addWidget(_table_item);
_bid = new QLineEdit{};
QIntValidator* _validator = new QIntValidator();
_validator->setBottom(0);
_bid->setValidator(_validator);
layout->addWidget(_bid);
_bid_button = new QPushButton{"Bid"};
layout->addWidget(_bid_button);
setLayout(layout);
this->setWindowTitle(QString::fromStdString(_user.name()));
QObject::connect(_combo, &QComboBox::currentTextChanged, this, &Collector_view::populate_table);
QObject::connect(_table, &QTableWidget::cellClicked, this, &Collector_view::populate_table_item);
QObject::connect(_bid_button, &QPushButton::clicked, this, &Collector_view::bid_item);
}
void Collector_view::update()
{
populate_table_item();
populate_table();
}
void Collector_view::populate_table()
{
std::string _category = _combo->currentText().toStdString();
_table->setRowCount(0);
std::vector<Item> items = _subject.get_items();
std::sort(items.begin(), items.end(), [](const Item& a, const Item& b) {return a.price() < b.price(); });
for (auto item : items)
{
if(_category == "All" || _category == item.category())
{
int row = _table->rowCount();
_table->insertRow(row);
_table->setItem(row, 0, new QTableWidgetItem{QString::fromStdString(item.name())});
_table->setItem(row, 1, new QTableWidgetItem{QString::fromStdString(item.category())});
_table->setItem(row, 2, new QTableWidgetItem{QString::number(item.price())});
}
}
}
void Collector_view::populate_table_item(){
//QMessageBox::critical(this, "Error", "Invalid input");
QModelIndexList selection = _table->selectionModel()->selectedIndexes();
if (selection.isEmpty())
{
_table_item->setRowCount(0);
return;
}
int row = selection.at(0).row();
std::string name = _table->item(row, 0)->text().toStdString();
Item item = _subject.find_item(name);
_table_item->setRowCount(0);
auto offers = item.offers();
std::sort(offers.begin(), offers.end(), [](const auto& a, const auto& b) {return std::get<1>(a) > std::get<1>(b); });
for( auto offer : offers){
int row = _table_item->rowCount();
_table_item->insertRow(row);
_table_item->setItem(row, 0, new QTableWidgetItem{QString::number(std::get<0>(offer))});
_table_item->setItem(row, 1, new QTableWidgetItem{QString::fromStdString(std::get<1>(offer))});
_table_item->setItem(row, 2, new QTableWidgetItem{QString::number(std::get<2>(offer))});
}
}
void Collector_view::bid_item(){
QModelIndexList selection = _table->selectionModel()->selectedIndexes();
if (selection.isEmpty())
{
return;
}
int row = selection.at(0).row();
std::string name = _table->item(row, 0)->text().toStdString();
Item item = _subject.find_item(name);
int bid = _bid->text().toInt();
if(bid < item.price()){
QMessageBox::critical(this, "Error", "Invalid input");
return;
}
_subject.bid(name,bid , _user.id(), "2023.06.13");
_bid->setText("");
}
@@ -0,0 +1,31 @@
#pragma once
#include "QWidget"
#include "QTableWidget"
#include "QVBoxLayout"
#include "QLineEdit"
#include "QPushButton"
#include "QComboBox"
#include "Subject.h"
#include "Service.h"
class Collector_view : public QWidget , virtual public Observer
{
Q_OBJECT
private:
Service& _subject;
QTableWidget* _table;
QTableWidget* _table_item;
User _user;
QComboBox* _combo;
QLineEdit* _bid;
QPushButton* _bid_button;
public:
Collector_view(Service& subject, User& user, QWidget* parent = nullptr);
void update() override;
void populate_table();
void populate_table_item();
void bid_item();
};
+10
View File
@@ -0,0 +1,10 @@
#include "Exam.h"
Exam::Exam(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
Exam::~Exam()
{}

Some files were not shown because too many files have changed in this diff Show More