Advertisement
Tvor0zhok

Графы класс

Oct 8th, 2022
698
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.69 KB | None | 0 0
  1. ///////////////////////////////////
  2. //            Graph.h            //
  3. ///////////////////////////////////
  4.  
  5. #pragma once
  6. #include <iostream>
  7. #include <fstream>
  8. #include <map>
  9. using namespace std;
  10.  
  11. /// <summary>
  12. /// Граф
  13. /// </summary>
  14. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  15. /// <typeparam name="Edge"> тип ребер графа (int по умолчанию) </typeparam>
  16. template <class Vertice, class Edge = int>
  17. class Graph
  18. {
  19.     /// <summary>
  20.     /// Количество вершин и ребер в графе
  21.     /// </summary>
  22.     int _N = 0, _M = 0;
  23.  
  24.     /// <summary>
  25.     /// Критерий ориентированности и взвешенности графа
  26.     /// </summary>
  27.     bool IsDirected = false, IsWeighted = false;
  28.  
  29.     /// <summary>
  30.     /// Список смежности графа
  31.     /// </summary>
  32.     map <Vertice, map<Vertice, Edge>> graph;
  33.  
  34. public:
  35.  
  36.     /// <summary>
  37.     /// Конструктор по умолчанию
  38.     /// </summary>
  39.     Graph() {};
  40.  
  41.     /// <summary>
  42.     /// Конструктор, создающий пустой граф, определяющий
  43.     /// ориентированность и взвешенность графа
  44.     /// </summary>
  45.     /// <param name="direction"> критерий ориентированности </param>
  46.     /// <param name="weighting"> критерий взвешенности </param>
  47.     Graph(string direction, string weighting)
  48.     {
  49.         if (direction == "directed") IsDirected = true;
  50.         if (weighting == "weighted") IsWeighted = true;
  51.     }
  52.  
  53.     /// <summary>
  54.     /// Конструктор, считывающий информацию из файла
  55.     /// или из консоли (stdin)
  56.     /// </summary>
  57.     /// <param name="filePath"> путь к файлу или ключевое слово stdin </param>
  58.     Graph(string filePath)
  59.     {
  60.         ifstream fin;
  61.  
  62.         if (filePath == "stdin") fin = ifstream(stdin);
  63.         else fin = ifstream(filePath);
  64.  
  65.         string cmd, direction, weighting;
  66.         fin >> cmd >> direction >> weighting;
  67.  
  68.         *this = Graph(direction, weighting);
  69.  
  70.         fin >> cmd >> _N;
  71.  
  72.         for (int i = 0; i < _N; ++i)
  73.         {
  74.             Vertice v; fin >> v;
  75.             graph.insert(pair<Vertice, map<Vertice, Edge>>(v, map<Vertice, Edge>()));
  76.         }
  77.  
  78.         fin >> cmd >> _M;
  79.  
  80.         for (int i = 0; i < _M; ++i)
  81.         {
  82.             Vertice u, v; Edge w; fin >> u >> v;
  83.  
  84.             if (!IsWeighted) w = 1;
  85.             else fin >> w;
  86.  
  87.             graph[u].insert(pair<Vertice, Edge>(v, w));
  88.             if (!IsDirected) graph[v].insert(pair<Vertice, Edge>(u, w));
  89.         }
  90.  
  91.         if (filePath != "stdin") fin.close();
  92.     }
  93.  
  94.     /// <summary>
  95.     /// Количество вершин графа
  96.     /// </summary>
  97.     /// <returns> количество вершин графа </returns>
  98.     int n() { return _N; }
  99.  
  100.     /// <summary>
  101.     /// Количество ребер графа
  102.     /// </summary>
  103.     /// <returns> количество ребер графа </returns>
  104.     int m() { return _M; }
  105.  
  106.     /// <summary>
  107.     /// Метод, выдающий информацию об
  108.     /// ориентированности графа
  109.     /// </summary>
  110.     /// <returns> true, если граф ориентированный, иначе - false </returns>
  111.     bool isDirected() { return IsDirected; }
  112.  
  113.     /// <summary>
  114.     /// Метод, выдающий информацию о
  115.     /// взвешенности графа
  116.     /// </summary>
  117.     /// <returns> true, если граф взвешенный, иначе - false </returns>
  118.     bool isWeighted() { return IsWeighted; }
  119.  
  120.     /// <summary>
  121.     /// Добавление вершины в граф
  122.     /// </summary>
  123.     /// <param name="v"> добавляемая в граф вершина </param>
  124.     void addVertice(Vertice v)
  125.     {
  126.         try
  127.         {
  128.             if (graph.find(v) != graph.end()) throw "Добавление вершины: заданная вершина уже есть в графе";
  129.             else
  130.             {
  131.                 ++_N;
  132.                 graph.insert(pair<Vertice, map<Vertice, Edge>>(v, map<Vertice, Edge>()));
  133.             }
  134.         }
  135.         catch (const char* msg)
  136.         {
  137.             cout << msg << "\n";
  138.         }
  139.     }
  140.  
  141.     /// <summary>
  142.     /// Удаление вершины из графа
  143.     /// </summary>
  144.     /// <param name="v"> удаляемая из графа вершина </param>
  145.     void removeVertice(Vertice v)
  146.     {
  147.         try
  148.         {
  149.             if (graph.find(v) == graph.end()) throw "Удаление вершины: в графе отсутствует заданная вершина";
  150.             else
  151.             {
  152.                 --_N; _M -= graph[v].size();
  153.  
  154.                 graph.erase(v);
  155.  
  156.                 for (auto p : graph)
  157.                     if (graph[p.first].find(v) != graph[p.first].end())
  158.                     {
  159.                         if (IsDirected) --_M;
  160.                         graph[p.first].erase(v);
  161.                     }
  162.             }
  163.         }
  164.         catch (const char* msg)
  165.         {
  166.             cout << msg << "\n";
  167.         }
  168.     }
  169.  
  170.     /// <summary>
  171.     /// Добавление ребра в граф
  172.     /// </summary>
  173.     /// <param name="u"> первая вершина ребра </param>
  174.     /// <param name="v"> вторая вершина ребра </param>
  175.     /// <param name="w"> вес ребра (для невзвешенных графов w = 1) </param>
  176.     void addEdge(Vertice u, Vertice v, Edge w)
  177.     {
  178.         try
  179.         {
  180.             if (graph.find(u) == graph.end() || graph.find(v) == graph.end()) throw "Добавление ребра: в графе отсутствует(ют) заданная(ые) вершина(ы)";
  181.             else if (!IsDirected && u == v) throw "Добавление ребра: невозможно добавить петлю в неориентированный граф";
  182.             else if (graph[u].find(v) != graph[u].end()) throw "Добавление ребра: заданное ребро уже есть в графе";
  183.             else
  184.             {
  185.                 ++_M;
  186.                 graph[u][v] = w;
  187.                 if (!IsDirected) graph[v][u] = w;
  188.             }
  189.         }
  190.         catch (const char* msg)
  191.         {
  192.             cout << msg << "\n";
  193.         }
  194.     }
  195.  
  196.     /// <summary>
  197.     /// Удаление ребра из графа
  198.     /// </summary>
  199.     /// <param name="u"> первая вершина ребра </param>
  200.     /// <param name="v"> вторая вершина ребра </param>
  201.     void removeEdge(Vertice u, Vertice v)
  202.     {
  203.         try
  204.         {
  205.             if (graph.find(u) == graph.end() || graph.find(v) == graph.end()) throw "Удаление ребра: в графе отсутствует(ют) заданная(ые) вершина(ы)";
  206.             else
  207.             {
  208.                 if (graph[u].find(v) == graph[u].end()) throw "Удаление ребра: в графе отсутствует заданное ребро";
  209.                 else
  210.                 {
  211.                     --_M;
  212.                     graph[u].erase(v);
  213.                     if (!IsDirected) graph[v].erase(u);
  214.                 }
  215.             }
  216.         }
  217.         catch (const char* msg)
  218.         {
  219.             cout << msg << "\n";
  220.         }
  221.     }
  222.  
  223.     /// <summary>
  224.     /// Очищение графа (ориентированность
  225.     /// и взвешенность остаются прежними)
  226.     /// </summary>
  227.     void clear()
  228.     {
  229.         _N = 0; _M = 0;
  230.         graph.clear();
  231.     }
  232.  
  233.     /// <summary>
  234.     /// Вывод информации о графе в файл или
  235.     /// на консоль (stdout)
  236.     /// </summary>
  237.     /// <param name="filePath"> путь к файлу или ключевое слово stdout </param>
  238.     void print(string filePath)
  239.     {
  240.         ofstream fout;
  241.  
  242.         if (filePath == "stdout") fout = ofstream(stdout);
  243.         else fout = ofstream(filePath);
  244.  
  245.         if (filePath != "stdout")
  246.         {
  247.             fout << "GRAPH ";
  248.  
  249.             if (IsDirected) fout << "directed ";
  250.             else fout << "undirected ";
  251.  
  252.             if (IsWeighted) fout << "weighted\n";
  253.             else fout << "unweighted\n";
  254.  
  255.             fout << "VERTICES: " << _N << "\n";
  256.  
  257.             for (auto p : graph)
  258.                 fout << p.first << "\n";
  259.  
  260.             fout << "EDGES: " << _M << "\n";
  261.  
  262.             for (auto p1 : graph)
  263.             {
  264.                 Vertice u = p1.first;
  265.  
  266.                 for (auto p2 : p1.second)
  267.                 {
  268.                     Vertice v = p2.first; Edge w = p2.second;
  269.  
  270.                     if (IsDirected || u < v)
  271.                     {
  272.                         fout << u << " " << v << " ";
  273.                         if (IsWeighted) fout << w;
  274.                         fout << "\n";
  275.                     }
  276.                 }
  277.             }
  278.  
  279.             fout.close();
  280.         }
  281.         else
  282.         {
  283.             fout << "GRAPH ";
  284.  
  285.             if (IsDirected) fout << "directed ";
  286.             else fout << "undirected ";
  287.  
  288.             if (IsWeighted) fout << "weighted\n";
  289.             else fout << "unweighted\n";
  290.  
  291.             fout << "VERTICES: " << _N << "\n";
  292.  
  293.             for (auto p : graph)
  294.                 fout << p.first << "\n";
  295.  
  296.             fout << "EDGES: " << _M << "\n";
  297.  
  298.             for (auto p1 : graph)
  299.             {
  300.                 Vertice u = p1.first;
  301.  
  302.                 fout << u << ": ";
  303.  
  304.                 for (auto p2 : p1.second)
  305.                 {
  306.                     Vertice v = p2.first; Edge w = p2.second;
  307.  
  308.                     if (!IsWeighted) fout << v << " ";
  309.                     else fout << "(" << v << ", " << w << ") ";
  310.                 }
  311.  
  312.                 fout << "\n";
  313.             }
  314.         }
  315.     }
  316. };
  317.  
  318. //////////////////////////////////////////////
  319. //            ConsoleInterface.h            //
  320. //////////////////////////////////////////////
  321.  
  322. #pragma once
  323. #include "Graph.h"
  324. #include <vector>
  325. #include <string>
  326.  
  327. /// <summary>
  328. /// Консольный интерфейс, работающий с одним графом
  329. /// </summary>
  330. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  331. /// <typeparam name="Edge"> тип ребер графа </typeparam>
  332. template <class Vertice, class Edge = int>
  333. class ConsoleInterface
  334. {
  335.     /// <summary>
  336.     /// Граф
  337.     /// </summary>
  338.     Graph<Vertice, Edge> g;
  339.  
  340.     /// <summary>
  341.     /// Вывод на консоль списка доступных команд
  342.     /// </summary>
  343.     void Hint()
  344.     {
  345.         cout << "+---------------------------------------+\n";
  346.         cout << "|             СПИСОК КОМАНД             |\n";
  347.         cout << "+---------------------------------------+\n";
  348.         cout << "|  1. CREATE GRAPH direction weighting  |\n";
  349.         cout << "|  2. CREATE GRAPH filePath             |\n";
  350.         cout << "|  3. ADD VERTICE v                     |\n";
  351.         cout << "|  4. REMOVE VERTICE v                  |\n";
  352.         cout << "|  5. ADD EDGE u v [w]                  |\n";
  353.         cout << "|  6. REMOVE EDGE u w                   |\n";
  354.         cout << "|  7. CLEAR GRAPH                       |\n";
  355.         cout << "|  8. PRINT GRAPH filePath              |\n";
  356.         cout << "|  9. GET HINT                          |\n";
  357.         cout << "|  10. EXIT                             |\n";
  358.         cout << "+---------------------------------------+\n";
  359.     }
  360.  
  361. public:
  362.  
  363.     /// <summary>
  364.     /// Конструктор по умолчанию
  365.     /// </summary>
  366.     ConsoleInterface() {};
  367.  
  368.     /// <summary>
  369.     /// Запуск интерфейса
  370.     /// </summary>
  371.     void Start()
  372.     {
  373.         Hint();
  374.  
  375.         while (true)
  376.         {
  377.             cout << ">> ";
  378.  
  379.             string w1; cin >> w1;
  380.  
  381.             if (w1 == "CREATE")
  382.             {
  383.                 string w2, w3; cin >> w2 >> w3;
  384.  
  385.                 if (w3 == "directed" || w3 == "undirected")
  386.                 {
  387.                     string w4; cin >> w4;
  388.                     g = Graph<Vertice, Edge>(w3, w4);
  389.                 }
  390.                 else g = Graph<Vertice, Edge>(w3);
  391.             }
  392.             else if (w1 == "ADD")
  393.             {
  394.                 string w2; cin >> w2;
  395.  
  396.                 if (w2 == "VERTICE")
  397.                 {
  398.                     Vertice w3; cin >> w3;
  399.                     g.addVertice(w3);
  400.                 }
  401.                 else
  402.                 {
  403.                     Vertice w3, w4; Edge w5; cin >> w3 >> w4;
  404.  
  405.                     if (!g.isWeighted()) w5 = 1;
  406.                     else cin >> w5;
  407.  
  408.                     g.addEdge(w3, w4, w5);
  409.                 }
  410.             }
  411.             else if (w1 == "REMOVE")
  412.             {
  413.                 string w2; cin >> w2;
  414.  
  415.                 if (w2 == "VERTICE")
  416.                 {
  417.                     Vertice w3; cin >> w3;
  418.                     g.removeVertice(w3);
  419.                 }
  420.                 else
  421.                 {
  422.                     Vertice w3, w4; cin >> w3 >> w4;
  423.                     g.removeEdge(w3, w4);
  424.                 }
  425.             }
  426.             else if (w1 == "CLEAR")
  427.             {
  428.                 string w2; cin >> w2;
  429.                 g.clear();
  430.             }
  431.             else if (w1 == "PRINT")
  432.             {
  433.                 string w2, w3; cin >> w2 >> w3;
  434.                 g.print(w3);
  435.             }
  436.             else if (w1 == "GET")
  437.             {
  438.                 string w2; cin >> w2;
  439.                 Hint();
  440.             }
  441.             else if (w1 == "EXIT")
  442.             {
  443.                 break;
  444.             }
  445.         }
  446.     }
  447. };
  448.  
  449. /////////////////////////////////////
  450. //            Graph.cpp            //
  451. /////////////////////////////////////
  452.  
  453. #include "ConsoleInterface.h"
  454. #include <Windows.h>
  455.  
  456. int main()
  457. {
  458.     SetConsoleCP(1251);
  459.     SetConsoleOutputCP(1251);
  460.  
  461.     ConsoleInterface<string, string> consoleInterface;
  462.     consoleInterface.Start();
  463.  
  464.     return 0;
  465. }
Advertisement
Comments
Add Comment
Please, Sign In to add comment
Advertisement