School Commit Init
This commit is contained in:
Binary file not shown.
@@ -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)
|
||||
Reference in New Issue
Block a user