Advertisement
anticlown

Graphs(3 sem.)

Nov 1st, 2023 (edited)
844
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.43 KB | None | 0 0
  1. //1. в заголовках создать два файла - Paths.h и Graph.h, закинуть в них код
  2. //2. создать исходные файлы Paths.cpp и Graph.cpp, закинуть в них код
  3. //3. создать файл GraphLab.cpp, закинуть в него код. Это файл с main
  4. // лаба готова :)
  5.  
  6.                                                         /* Paths.h file start */
  7.  
  8. #pragma once
  9. #include <vector>
  10.  
  11. class Paths
  12. {
  13. public:
  14.     struct DistancePoint
  15.     {
  16.         int m_point;
  17.         int m_distancePrev;
  18.     };
  19.  
  20.     struct Path
  21.     {
  22.         std::vector<DistancePoint> m_points;
  23.         int m_length;
  24.     };
  25.  
  26. private:
  27.     std::vector<Path> m_paths;
  28.  
  29. public:
  30.     static void printPath(const Path& path);
  31.  
  32.     Paths(const Paths& paths);
  33.  
  34.     Paths();
  35.  
  36.     const Paths& operator=(const Paths& paths);
  37.  
  38.     Path& operator[](const int index);
  39.  
  40.     void addPath(const Path& path);
  41.  
  42.     void clear();
  43.  
  44.     int getLength();
  45.  
  46.     void insertInFront(const int pathIndex, const DistancePoint& distancePoint);
  47.  
  48.     void sort();
  49.  
  50.     void printPaths();
  51.  
  52. };
  53.  
  54.                                                 /* Paths.h file end */
  55.  
  56.  
  57.                                                 /* Graph.h file start */
  58.  
  59. #pragma once
  60. #include <vector>
  61. #include <algorithm>
  62. #include "Paths.h"
  63. #define INFINITY_GRAPH INT_MAX
  64.  
  65. class Graph
  66. {
  67. private:
  68.     std::vector<std::vector<int>> m_adjacencyMatrix;
  69.  
  70.     //Recursive function which returns all paths from point v to point x
  71.     Paths findPathPrivate(const std::vector<std::vector<int>>& a, std::vector<bool>& visited, int n, int v, int x, int currentPathLength, Paths& paths, Paths::Path& currentPath);
  72.  
  73.     //Returns minimum distance from all unvisited vertices to current
  74.     int minDist(const std::vector<int>& dist, const std::vector<bool>& tSet);
  75.  
  76. public:
  77.     //Initialize adjacency matrix from parameter with 0(MACHINE INFINITY)
  78.     static void initGraph(std::vector<std::vector<int>>& adjacencyMatrix);
  79.  
  80.     //Constructor copy adjacency matrix from parameter to class field
  81.     Graph(const std::vector<std::vector<int>>& adjacencyMatrix);
  82.  
  83.     //This function calls recursive function findPathPrivate, but prepare all parameters to simplify usage for developer
  84.     Paths findAllPaths(const int startPoint, const int finishPoint);
  85.  
  86.     //Function finds shortest path between two points
  87.     Paths::Path findShortestPath(const int startPoint, const int finishPoint);
  88.  
  89.     //Function finds longest path between two points
  90.     Paths::Path findLongestPath(const int startPoint, const int finishPoint);
  91.  
  92.     //Finds graph center
  93.     int findCenter();
  94.  
  95.     //Prints adjacency matrix, that represents graph
  96.     void print_adjacencyMatrix();
  97. };
  98.  
  99.                                                     /* Graph.h file end */
  100.  
  101.  
  102.                                                     /* Paths.cpp file start */
  103.  
  104. #include "Paths.h"
  105.  
  106. void Paths::printPath(const Path& path)
  107. {
  108.     if (path.m_points.size())
  109.     {
  110.         printf("<%d>", path.m_points[0].m_point + 1);
  111.         for (int j = 1; j < path.m_points.size(); ++j)
  112.             printf("  (%d)->  <%d>", path.m_points[j].m_distancePrev, path.m_points[j].m_point + 1);
  113.         printf("  Количество точек: %d, Длина: %d", (int)path.m_points.size(), path.m_length);
  114.         printf("\n");
  115.     }
  116. }
  117.  
  118. Paths::Paths(const Paths& paths)
  119. {
  120.     this->m_paths = paths.m_paths;
  121. }
  122.  
  123. Paths::Paths()
  124. {
  125.     m_paths.resize(0);
  126. }
  127.  
  128. const Paths& Paths::operator=(const Paths& paths)
  129. {
  130.     this->m_paths = paths.m_paths;
  131.     return *this;
  132. }
  133.  
  134. Paths::Path& Paths::operator[](const int index)
  135. {
  136.     return m_paths[index];
  137. }
  138.  
  139. void Paths::addPath(const Path& path)
  140. {
  141.     m_paths.push_back(path);
  142. }
  143.  
  144. void Paths::clear()
  145. {
  146.     m_paths.resize(0);
  147. }
  148.  
  149. int Paths::getLength()
  150. {
  151.     return m_paths.size();
  152. }
  153.  
  154. void Paths::insertInFront(const int pathIndex, const DistancePoint& distancePoint)
  155. {
  156.     m_paths[pathIndex].m_points.insert(m_paths[pathIndex].m_points.begin(), distancePoint);
  157. }
  158.  
  159. void Paths::sort()
  160. {
  161.     for (int i = 1; i < m_paths.size(); ++i)
  162.         for (int j = 0; j < m_paths.size() - i; ++j)
  163.             if (m_paths[j].m_length > m_paths[j + 1].m_length)
  164.             {
  165.                 Path temp = m_paths[j];
  166.                 m_paths[j] = m_paths[j + 1];
  167.                 m_paths[j + 1] = temp;
  168.             }
  169. }
  170.  
  171. void Paths::printPaths()
  172. {
  173.     int i{ 1 };
  174.     for (const Path& path : m_paths)
  175.     {
  176.         printf("Path #%d: ", i);
  177.         this->printPath(path);
  178.         ++i;
  179.     }
  180. }
  181.  
  182.                                                     /* Paths.cpp file end */
  183.  
  184.                                                     /* Graph.cpp file start */
  185.  
  186. #include "Graph.h"
  187.  
  188. Paths Graph::findPathPrivate(const std::vector<std::vector<int>>& a, std::vector<bool>& visited, int n, int v, int x, int currentPathLength, Paths& paths, Paths::Path& currentPath)
  189. {
  190.     //static Paths paths;
  191.     //static Paths::Path currentPath;
  192.     if (v == x) {
  193.         currentPath.m_length = currentPathLength;
  194.         paths.addPath(currentPath);
  195.         return paths;
  196.     }
  197.  
  198.     visited[v] = true;
  199.     for (int i = 0; i < n; ++i)
  200.         if (/*a[v][i]*/ a[v][i] != INFINITY_GRAPH && !visited[i])
  201.         {
  202.             currentPath.m_points.push_back({i, a[v][i]});
  203.             currentPathLength += a[v][i];
  204.             findPathPrivate(a, visited, n, i, x, currentPathLength, paths, currentPath);
  205.             currentPath.m_points.pop_back();
  206.             currentPathLength -= a[v][i];
  207.         }
  208.     visited[v] = false;
  209.     return paths;
  210. }
  211.  
  212. int Graph::minDist(const std::vector<int>& dist, const std::vector<bool>& tSet)
  213. {
  214.  
  215.     int min = INT_MAX, index{ 0 };
  216.  
  217.     for (int i = 0; i < m_adjacencyMatrix.size(); ++i)
  218.     {
  219.         if (tSet[i] == false && dist[i] <= min)
  220.         {
  221.             min = dist[i];
  222.             index = i;
  223.         }
  224.  
  225.     }
  226.  
  227.     return index;
  228. }
  229.  
  230. void Graph::initGraph(std::vector<std::vector<int>>& adjacencyMatrix)
  231. {
  232.     for (int i = 0; i < adjacencyMatrix.size(); ++i)
  233.     {
  234.         std::fill(adjacencyMatrix[i].begin(), adjacencyMatrix[i].end(), INFINITY_GRAPH);
  235.         adjacencyMatrix[i][i] = 0;
  236.     }
  237. }
  238.  
  239. Graph::Graph(const std::vector<std::vector<int>>& adjacencyMatrix)
  240. {
  241.     m_adjacencyMatrix = adjacencyMatrix;
  242. }
  243.  
  244. Paths Graph::findAllPaths(const int startPoint, const int finishPoint)
  245. {
  246.     std::vector<bool> visited{};
  247.     visited.resize(m_adjacencyMatrix.size());
  248.     Paths paths;
  249.     Paths::Path currentPath;
  250.     paths = this->findPathPrivate(m_adjacencyMatrix, visited, visited.size(), startPoint, finishPoint, 0, paths, currentPath);
  251.     for (int i = 0; i < paths.getLength(); ++i)
  252.         paths.insertInFront(i, { startPoint, 0});
  253.     paths.sort();
  254.     return paths;
  255. }
  256.  
  257. Paths::Path Graph::findShortestPath(const int startPoint, const int finishPoint)
  258. {
  259.     std::vector<int> dist; // integer array to calculate minimum distance for each node.  
  260.     dist.resize(m_adjacencyMatrix.size());
  261.     std::fill(dist.begin(), dist.end(), /*INT_MAX*/INFINITY_GRAPH);
  262.     std::vector<bool> tSet;// boolean array to mark visted/unvisted for each node.
  263.     tSet.resize(m_adjacencyMatrix.size());
  264.     std::fill(tSet.begin(), tSet.end(), false);
  265.  
  266.     dist[startPoint] = 0;
  267.  
  268.     for (int i = 0; i < dist.size(); ++i)
  269.     {
  270.         int m = minDist(dist, tSet); // vertex not yet included.
  271.         tSet[m] = true;// m with minimum distance included in Tset.
  272.         for (int i = 0; i < dist.size(); ++i)
  273.         {
  274.             // Updating the minimum distance for the particular node.
  275.             if (!tSet[i] && /*m_adjacencyMatrix[m][i]*/ m_adjacencyMatrix[m][i] != INFINITY_GRAPH && dist[m] != /*INT_MAX*/INFINITY_GRAPH && dist[m] + m_adjacencyMatrix[m][i] < dist[i])
  276.                 dist[i] = dist[m] + m_adjacencyMatrix[m][i];
  277.         }
  278.     }
  279.  
  280.     Paths::Path path;
  281.     if (dist[finishPoint] != /*INT_MAX*/INFINITY_GRAPH)
  282.     {
  283.         int current{ finishPoint };
  284.         while (current != startPoint)
  285.             for (int i = 0; i < m_adjacencyMatrix.size(); ++i)
  286.                 if (dist[current] - m_adjacencyMatrix[i][current] == dist[i] && m_adjacencyMatrix[i][current] != 0)
  287.                 {
  288.                     path.m_points.push_back({ current, m_adjacencyMatrix[i][current] });
  289.                     current = i;
  290.                     break;
  291.                 }
  292.         path.m_points.push_back({ startPoint, 0 });
  293.         path.m_length = dist[finishPoint];
  294.         reverse(path.m_points.begin(), path.m_points.end());
  295.     }
  296.     return path;
  297. }
  298.  
  299. Paths::Path Graph::findLongestPath(const int startPoint, const int finishPoint)
  300. {
  301.     Paths paths = findAllPaths(startPoint, finishPoint);
  302.     if (paths.getLength())
  303.         return paths[paths.getLength() - 1];
  304.     return Paths::Path();
  305. }
  306.  
  307. int Graph::findCenter()
  308. {
  309.     std::vector<std::vector<int>> m_adjacencyMatrixCopy{ m_adjacencyMatrix };
  310.     //Floyd algorithm
  311.     for (int k = 0; k < m_adjacencyMatrixCopy.size(); ++k)
  312.         for (int i = 0; i < m_adjacencyMatrixCopy.size(); ++i)
  313.             for (int j = 0; j < m_adjacencyMatrixCopy.size(); ++j)
  314.                 if (m_adjacencyMatrixCopy[i][k] != INFINITY_GRAPH && m_adjacencyMatrixCopy[k][j] != INFINITY_GRAPH)
  315.                     m_adjacencyMatrixCopy[i][j] = std::min(m_adjacencyMatrixCopy[i][j], m_adjacencyMatrixCopy[i][k] + m_adjacencyMatrixCopy[k][j]);
  316.  
  317.     //Find eccentricitys
  318.     std::vector<int> eccentricitys;
  319.     for (int i = 0; i < m_adjacencyMatrixCopy.size(); ++i)
  320.     {
  321.         int max{ 0 };
  322.         for (int j = 0; j < m_adjacencyMatrixCopy.size(); ++j)
  323.             if (m_adjacencyMatrixCopy[j][i] > max)
  324.                 max = m_adjacencyMatrixCopy[j][i];
  325.         eccentricitys.push_back(max);
  326.     }
  327.  
  328.     //Return lowest eccentricity
  329.     //return *std::min_element(eccentricitys.begin(), eccentricitys.end());
  330.     int minIndex{ 0 };
  331.     for (int i = 1; i < eccentricitys.size(); ++i)
  332.         if (eccentricitys[i] < eccentricitys[minIndex])
  333.             minIndex = i;
  334.     return minIndex;
  335. }
  336.  
  337. void Graph::print_adjacencyMatrix()
  338. {
  339.     for (int i = 0; i < m_adjacencyMatrix.size(); ++i)
  340.     {
  341.         for (int j = 0; j < m_adjacencyMatrix.size(); ++j)
  342.         {
  343.             if (m_adjacencyMatrix[i][j] == INFINITY_GRAPH)
  344.                 printf("%7s", " inf");
  345.             else
  346.                 printf(" %5d ", m_adjacencyMatrix[i][j]);
  347.         }
  348.         printf("\n");
  349.     }
  350. }
  351.  
  352.                                                     /* Graph.cpp file end */
  353.  
  354.                                                     /* GraphLab.cpp(main) file start */
  355.  
  356. #include <iostream>
  357. #include "Graph.h"
  358. #include "Paths.h"
  359.  
  360. void createGraph1(std::vector<std::vector<int>>& mtrx1)
  361. {
  362.     const int verticesNum{ 5 };
  363.     mtrx1.resize(verticesNum);
  364.     for (int i = 0; i < verticesNum; ++i)
  365.         mtrx1[i].resize(verticesNum);
  366.     Graph::initGraph(mtrx1);
  367.     mtrx1[0][1] = 10;
  368.     mtrx1[0][3] = 30;
  369.     mtrx1[0][4] = 100;
  370.     mtrx1[1][2] = 50;
  371.     mtrx1[2][4] = 10;
  372.     mtrx1[3][2] = 20;
  373.     mtrx1[3][4] = 60;
  374. }
  375.  
  376. void createGraph2(std::vector<std::vector<int>>& mtrx2)
  377. {
  378.     const int verticesNum{ 7 };
  379.     mtrx2.resize(verticesNum);
  380.     for (int i = 0; i < verticesNum; ++i)
  381.         mtrx2[i].resize(verticesNum);
  382.     Graph::initGraph(mtrx2);
  383.    
  384.    
  385.     mtrx2[0][1] = 10;
  386.     mtrx2[1][2] = 1;
  387.     mtrx2[1][4] = 10;
  388.     mtrx2[2][5] = 2;
  389.     mtrx2[3][0] = 10;
  390.     mtrx2[3][1] = 10;
  391.     mtrx2[3][2] = 10;
  392.     mtrx2[4][6] = 4;
  393.     mtrx2[5][4] = 3;
  394.     mtrx2[5][3] = 10;
  395.     mtrx2[6][5] = 10;
  396. }
  397.  
  398. void createGraph3(std::vector<std::vector<int>>& mtrx3)
  399. {
  400.     const int verticesNum{ 5 };
  401.     mtrx3.resize(verticesNum);
  402.     for (int i = 0; i < verticesNum; ++i)
  403.         mtrx3[i].resize(verticesNum);
  404.     Graph::initGraph(mtrx3);
  405.  
  406.  
  407.     mtrx3[0][1] = 1;
  408.     mtrx3[1][2] = 2;
  409.     mtrx3[3][1] = 1;
  410.     mtrx3[3][2] = 3;
  411.     mtrx3[4][3] = 5;
  412.     mtrx3[2][4] = 4;
  413.     mtrx3[2][3] = 2;
  414. }
  415.  
  416. int main()
  417. {
  418.     setlocale(LC_ALL, "Russian");
  419.     int mtrxNum{ 0 };
  420.     std::cout << "Введите номер графа для загрузки(доступно 3): ";
  421.     std::cin >> mtrxNum;
  422.     std::vector<std::vector<int>> mtrx;
  423.     switch (mtrxNum)
  424.     {
  425.     case 1:
  426.         createGraph1(mtrx);
  427.         break;
  428.     case 2:
  429.         createGraph2(mtrx);
  430.         break;
  431.     case 3:
  432.         createGraph3(mtrx);
  433.         break;
  434.     default:
  435.         exit(0);
  436.     }
  437.    
  438.     Graph graph{ mtrx };
  439.  
  440.     int start{ 0 };
  441.     int finish{ 0 };
  442.     std::cout << "Введите начальную точку: ";
  443.     std::cin >> start;
  444.     std::cout << "Введите конечную точку: ";
  445.     std::cin >> finish;
  446.     --start;
  447.     --finish;
  448.  
  449.     printf("Матрица смежности графа:\n");
  450.     graph.print_adjacencyMatrix();
  451.  
  452.     Paths paths;
  453.  
  454.     paths = graph.findAllPaths(start, finish);
  455.     if (paths.getLength())
  456.     {
  457.         printf("\n\n\n");
  458.         printf("Все пути в графе от точки %d до точки %d по возрастанию длины:\n", start + 1, finish + 1);
  459.         paths.printPaths();
  460.         printf("\n\n");
  461.  
  462.  
  463.         printf("\n");
  464.         Paths::Path path;
  465.  
  466.         printf("Кратчайший путь: ");
  467.         path = graph.findShortestPath(start, finish);
  468.         Paths::printPath(path);
  469.  
  470.         printf("\n");
  471.         printf("Длиннейший путь: ");
  472.         path = graph.findLongestPath(start, finish);
  473.         Paths::printPath(path);
  474.     }
  475.     else
  476.         printf("\nВершина %d недостижима из вершины %d", finish + 1, start + 1);
  477.  
  478.     printf("\n");
  479.     printf("\nЦентр графа: %d\n",graph.findCenter() + 1);
  480. }
  481.  
  482.                                                         /* GraphLab main file end */
  483.  
  484.  
  485.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement