commit 1c8c1b92a70f64f81c4199d7d62c013ae51e50ff Author: Rendo Date: Sun Jun 21 23:12:29 2026 +0500 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba2906d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +main diff --git a/input.txt b/input.txt new file mode 100644 index 0000000..2503c88 --- /dev/null +++ b/input.txt @@ -0,0 +1,6 @@ +C 4 +0 0 +0 1 1 1 +1 0 1 1 +1 1 0 0 +1 1 0 1 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..bdbdb9e --- /dev/null +++ b/main.cpp @@ -0,0 +1,446 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +// Базовый класс представления +class IGRepr { +public: + virtual void from_file(string filepath) = 0; + virtual void to_file(string filepath,bool is_oriented, bool is_weighted) = 0; + virtual void add_edge(int vertex_a, int vertex_b, int weight) = 0; + virtual void remove_edge(int vertex_a, int vertex_b) = 0; + virtual int change_weight(int vertex_a, int vertex_b, int new_weight) = 0; + virtual vector> get_edges() = 0; + virtual ~IGRepr() {}; + virtual int count_vertices() = 0; +}; + +// Представление в виде матрицы смежности +class AdjMatrix: public IGRepr { +private: + vector> matrix; +public: + AdjMatrix(int n = 0); + virtual void from_file(string filepath) override; + virtual void to_file(string filepath,bool is_oriented, bool is_weighted) override; + virtual void add_edge(int vertex_a, int vertex_b, int weight) override; + virtual void remove_edge(int vertex_a, int vertex_b) override; + virtual int change_weight(int vertex_a, int vertex_b, int new_weight) override; + virtual vector> get_edges() override; + virtual int count_vertices() override; +}; + +AdjMatrix::AdjMatrix(int n) { + for (int i = 0; i < n; i++){ + vector temp; + for (int j = 0; j < n; j++) + temp.push_back(0); + matrix.push_back(temp); + } +} + +void AdjMatrix::add_edge(int vertex_a, int vertex_b, int weight){ + if (matrix[vertex_a][vertex_b] != 0) return; + matrix[vertex_a][vertex_b] = weight; +} + +void AdjMatrix::remove_edge(int vertex_a, int vertex_b) { + matrix[vertex_a][vertex_b] = 0; +} +int AdjMatrix::change_weight(int vertex_a, int vertex_b, int new_weight) { + int old_weight = matrix[vertex_a][vertex_b]; + + matrix[vertex_a][vertex_b] = new_weight; + + return old_weight; +} +void AdjMatrix::from_file(string filepath) { + ifstream file{filepath}; + string buffer; + + // Чтение первых двух строк + + getline(file,buffer); + istringstream initial_iss{buffer}; + char _type; + initial_iss >> _type; + int vertices; + initial_iss >> vertices; + for(int i = 0; i < vertices; i++) { + matrix.push_back(vector{}); + for(int j = 0; j < vertices; j++) { + matrix[i].push_back(0); + } + } + + getline(file,buffer); + + int from_vertex = 0; + // Чтение непосредственно данных + while(getline(file,buffer)) { + istringstream iss{buffer}; + int to_vertex = 0; + int weight; + while (iss >> weight) { + matrix[from_vertex][to_vertex] = weight; + to_vertex += 1; + } + from_vertex += 1; + } + + file.close(); +} +void AdjMatrix::to_file(string filepath,bool is_oriented, bool is_weighted) { + ofstream file{filepath}; + + file << 'C' << matrix.size() << " " << endl; + file << (int)is_oriented << " " << (int)is_weighted << endl; + for(int i = 0; i < matrix.size(); i++){ + for(int j = 0; j < matrix[i].size(); j++) + file << matrix[i][j] << " "; + file << endl; + } +} + +vector> AdjMatrix::get_edges() { + vector> result; + for(int i = 0; i < matrix.size(); i++) + for (int j = 0; j < matrix[i].size(); j++) + if (matrix[i][j] != 0) + result.push_back({i,j,matrix[i][j]}); + return result; +} + +int AdjMatrix::count_vertices() { + return matrix.size(); +} + +// Представление в виде списка смежных вершин +class AdjList: public IGRepr { +private: + vector>> list; +public: + AdjList(int n=0); + virtual void from_file(string filepath) override; + virtual void to_file(string filepath,bool is_oriented, bool is_weighted) override; + virtual void add_edge(int vertex_a, int vertex_b, int weight) override; + virtual void remove_edge(int vertex_a, int vertex_b) override; + virtual int change_weight(int vertex_a, int vertex_b, int new_weight) override; + virtual vector> get_edges() override; + virtual int count_vertices() override; +}; + +AdjList::AdjList(int n){ + for(int i = 0; i < n; i++) + list.push_back({}); +} + +void AdjList::add_edge(int vertex_a, int vertex_b, int weight){ + auto found = list[vertex_a].lower_bound({vertex_b,INT_MIN}); + if (found != list[vertex_a].end() && found->first == vertex_b) + return; + list[vertex_a].insert({vertex_b,weight}); +} + +void AdjList::remove_edge(int vertex_a, int vertex_b) { + auto found = list[vertex_a].lower_bound({vertex_b,INT_MIN}); + if (found == list[vertex_a].end() || found->first != vertex_b) + return; + list[vertex_a].erase(*found); +} +int AdjList::change_weight(int vertex_a, int vertex_b, int new_weight) { + auto found = list[vertex_a].lower_bound({vertex_b,INT_MIN}); + int old_weight = found->second; + + list[vertex_a].erase(found); + list[vertex_a].insert({vertex_b,new_weight}); + + return old_weight; + +} +void AdjList::from_file(string filepath) { + ifstream file{filepath}; + string buffer; + + // Чтение первых двух строк + + getline(file,buffer); + istringstream initial_iss{buffer}; + char _type; + initial_iss >> _type; + int vertices; + initial_iss >> vertices; + for(int i = 0; i < vertices; i++) { + list.push_back(set>{}); + } + + getline(file,buffer); + istringstream meta_iss{buffer}; + bool _oriented, weighted; + meta_iss >> _oriented >> weighted; + + int from_vertex = 0; + // Чтение непосредственно данных + if (weighted) { + while(getline(file,buffer)) { + istringstream iss{buffer}; + int to_vertex, weight; + while (iss >> to_vertex >> weight) { + list[from_vertex].insert({to_vertex,weight}); + } + from_vertex += 1; + } + } + else { + while(getline(file,buffer)) { + istringstream iss{buffer}; + int to_vertex; + while (iss >> to_vertex) { + list[from_vertex].insert({to_vertex,1}); + } + from_vertex += 1; + } + } + file.close(); +} +void AdjList::to_file(string filepath,bool is_oriented, bool is_weighted) { + ofstream file{filepath}; + + file << 'L' << " " << list.size() << endl; + file << (int)is_oriented << " " << (int)is_weighted << endl; + if (is_weighted) + for(int i = 0; i < list.size(); i++){ + for(auto j = list[i].begin(); j != list[i].end(); ++j) + file << j->first << " " << j-> second << " "; + file << endl; + } + else + for(int i = 0; i < list.size(); i++){ + for(auto j = list[i].begin(); j != list[i].end(); ++j) + file << j->first << " "; + file << endl; + } +} + +vector> AdjList::get_edges() { + vector> result; + for(int i = 0; i < list.size(); i++) + for (auto j = list[i].begin(); j != list[i].end(); ++j) + result.push_back({i,j->first,j->second}); + return result; +} + +int AdjList::count_vertices() { + return list.size(); +} + +// Представление в виде списка рёбер +class EdgeList: public IGRepr { +public: + vector> list; + virtual void from_file(string filepath) override; + virtual void to_file(string filepath,bool is_oriented, bool is_weighted) override; + virtual void add_edge(int vertex_a, int vertex_b, int weight) override; + virtual void remove_edge(int vertex_a, int vertex_b) override; + virtual int change_weight(int vertex_a, int vertex_b, int new_weight) override; + virtual vector> get_edges() override; + virtual int count_vertices() override; +}; +void EdgeList::add_edge(int vertex_a, int vertex_b, int weight){ + auto found = find_if(list.begin(),list.end(), + [vertex_a,vertex_b](const tuple& edge) { + return get<0>(edge) == vertex_a && get<1>(edge) == vertex_b; + } + ); + if (found != list.end()) + return; + list.push_back({vertex_a,vertex_b,weight}); +} + +void EdgeList::remove_edge(int vertex_a, int vertex_b) { + auto found = find_if(list.begin(),list.end(), + [vertex_a,vertex_b](const tuple& edge) { + return get<0>(edge) == vertex_a && get<1>(edge) == vertex_b; + } + ); + + list.erase(found); +} +int EdgeList::change_weight(int vertex_a, int vertex_b, int new_weight) { + auto found = find_if(list.begin(),list.end(), + [vertex_a,vertex_b](const tuple& edge) { + return get<0>(edge) == vertex_a && get<1>(edge) == vertex_b; + } + ); + int old_weight = get<2>(*found); + + list.erase(found); + list.push_back({vertex_a,vertex_b,new_weight}); + + return old_weight; + +} +void EdgeList::from_file(string filepath) { + ifstream file{filepath}; + string buffer; + + // Чтение первых двух строк + + getline(file,buffer); + istringstream initial_iss{buffer}; + char _type; + initial_iss >> _type; + int _vertices,edges; + initial_iss >> _vertices >> edges; + getline(file,buffer); + istringstream meta_iss{buffer}; + bool _oriented, weighted; + meta_iss >> _oriented >> weighted; + + // Чтение непосредственно данных + if (weighted) { + while(getline(file,buffer)) { + istringstream iss{buffer}; + int from_vertex, to_vertex, weight; + iss >> from_vertex >> to_vertex >> weight; + list.push_back({from_vertex,to_vertex,weight}); + } + } + else { + while(getline(file,buffer)) { + istringstream iss{buffer}; + int from_vertex, to_vertex; + iss >> from_vertex >> to_vertex; + list.push_back({from_vertex,to_vertex,1}); + } + } + file.close(); +} +void EdgeList::to_file(string filepath,bool is_oriented, bool is_weighted) { + ofstream file{filepath}; + + file << 'E' << " " << count_vertices() << " " << list.size() << endl; + file << (int)is_oriented << " " << (int)is_weighted << endl; + if (is_weighted) + for(auto i = list.begin(); i < list.end(); ++i){ + file << get<0>(*i) << " " << get<1>(*i) << " " << get<2>(*i) << endl; + } + else + for(auto i = list.begin(); i < list.end(); ++i){ + file << get<0>(*i) << " " << get<1>(*i) << endl; + } +} +vector> EdgeList::get_edges() { + return list; +} +int EdgeList::count_vertices() { + int max_vertex = 0; + for(int i = 0; i < list.size(); i++) + max_vertex = max(max_vertex,max(get<0>(list[i]),get<1>(list[i]))); + return max_vertex + 1; +} + +// Непосредственно граф +class Graph { +private: + IGRepr* repr; + bool oriented; + bool weighted; + void transformTo(IGRepr* new_repr); +public: + void readGraph(string fileName); + void writeGraph(string fileName); + void addEdge(int from, int to, int weight); + void removeEdge(int from, int to); + int changeEdge(int from, int to, int newWeight); + void transformToAdjList(); + void transformToAdjMatrix(); + void transformToListOfEdges(); + ~Graph(); +}; + +void Graph::readGraph(string fileName) { + ifstream file{fileName}; + string buffer; + getline(file,buffer); + switch (buffer[0]) { + case 'C': + repr = new AdjMatrix; + break; + case 'E': + repr = new EdgeList; + break; + case 'L': + repr = new AdjList; + break; + } + + repr->from_file(fileName); + getline(file,buffer); + istringstream stream {buffer}; + stream >> oriented >> weighted; + file.close(); +} + +void Graph::writeGraph(string fileName){ + repr->to_file(fileName,oriented,weighted); +} + +void Graph::addEdge(int from, int to, int weight) { + repr->add_edge(from, to, weight); + if (oriented == false) + repr->add_edge(to, from, weight); +} + +void Graph::removeEdge(int from, int to) { + repr->remove_edge(from, to); + if (oriented == false) + repr->remove_edge(to, from); +} +int Graph::changeEdge(int from, int to, int newWeight){ + if (weighted && newWeight != 1) + weighted = false; + return repr->change_weight(from, to, newWeight); +} + +Graph::~Graph() { + delete repr; +} + +void Graph::transformTo(IGRepr* new_repr) { + auto edges = repr->get_edges(); + for (int i = 0; i < edges.size(); i++) + new_repr->add_edge(get<0>(edges[i]),get<1>(edges[i]) ,get<2>(edges[i]) ); + delete repr; + repr = new_repr; +} +void Graph::transformToAdjList() { + transformTo(new AdjList(repr->count_vertices())); +} +void Graph::transformToAdjMatrix(){ + transformTo(new AdjMatrix(repr->count_vertices())); +} + +void Graph::transformToListOfEdges() { + transformTo(new EdgeList); +} + +int main() { + Graph graph; + graph.readGraph("input.txt"); + graph.transformToAdjList(); + graph.writeGraph("output_adj_list.txt"); + graph.transformToListOfEdges(); + graph.writeGraph("output_edge_list.txt"); + graph.transformToAdjMatrix(); + graph.writeGraph("output_adj_matrix.txt"); + + return 0; +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..9745b22 --- /dev/null +++ b/makefile @@ -0,0 +1,2 @@ +main: main.cpp + g++ -lstdc++ main.cpp -o main