Advertisement
Karolina99

Graph - adjacency matrix

Jan 15th, 2020
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.66 KB | None | 0 0
  1. #include <iostream>
  2. #include <queue>
  3. #include <stack>
  4. #include <vector>
  5.  
  6. using namespace std;
  7.  
  8. struct edge //krawedz
  9. {
  10.     int s; //poczatek krawedzi
  11.     int t; //koniec krawedzi
  12. };
  13.  
  14. class Graph
  15. {
  16.     private:
  17.         int** adjMatrix; //macierz sasiedztwa, dwuwymiarowa
  18.         int n;              //liczba węzłów
  19.     public:
  20.         Graph(int n, int m, edge edges[], bool directed = false);   //tworzy graf w oparciu o podaną listę krawędzi, konstruktor
  21.         int edgeCnt();                  //zwraca liczbę krawędzi
  22.         int nodeCnt();                  //zwraca liczbę węzłów
  23.         void insertEdge(int u, int v);          //wstawia krawędź
  24.         void deleteEdge(int u, int v);          //usuwa krawędź
  25.         bool check(int u, int v);           //sprawdza czy istnieje krawędź
  26.         void bfs(int s);                //wyświetla węzły w porządku odwiedzenia
  27.         void bfs(int s, int* connectedComp, int components);
  28.         void dfs(int s);                //wyświetla węzły w porządku odwiedzenia
  29.         void visit(int *visited, int s);
  30.         int* connectedComponents(); //metoda (działająca dla grafu nieskierowanego), która dla każdego węzła zwraca nr spójnej składowej, do której węzeł należy
  31.         //int* stronglyConnectedComponents(); // metoda (działająca dla grafu skierowanego), która dla każdego węzła zwraca nr silnie spójnej składowej, do której węzeł należy
  32.         int* Dijkstra(int s); //s-wezel zrodlowy, zwraca tabele odleglosci
  33.         vector<int> path(int s, int e); //zwraca najkrotsza sciezke pomiedzy wybrana para wezlow
  34.         //double** WarshallFloyd(); //zwraca macierz odleglosci
  35.         friend ostream& operator<<(ostream& out, Graph& g); //wyswietla macierz sasiedztwa na ekranie
  36.         //~Graph(); //destruktor
  37.         //inne potrzebne/pomocnicze metody składowe
  38. };
  39.  
  40. Graph::Graph(int n, int m, edge edges[], bool directed) //tu juz nie piszemy jeszcze raz true lub false
  41. {
  42.     this->n = n;
  43.  
  44.     adjMatrix = new int* [n]; //tworzymy zerowy wiersz
  45.     for (int i = 0; i < n; ++i) //tworzymy pozostale wiersze
  46.     {
  47.         adjMatrix[i] = new int[n];
  48.     }
  49.  
  50.     //cala macierz sasiedztwa wypelniam 0
  51.     for (int i = 0; i < n; i++)
  52.     {
  53.         for (int j = 0; j < n; j++)
  54.         {
  55.             adjMatrix[i][j] = 0;
  56.         }
  57.     }
  58.  
  59.     //wpisuje do macierzy 1, jesli krawedz laczaca wierzcholki istnieje
  60.     //dla grafu nieskierowanego
  61.     for (int i = 0; i < m; i++)
  62.     {
  63.         //dla grafu nieskierowanego, czyli macierz jest symetryczna wzgledem glownej przekatnej
  64.         adjMatrix[edges[i].s][edges[i].t] = 1;
  65.         adjMatrix[edges[i].t][edges[i].s] = 1;
  66.     }
  67.  
  68.     //dla grafu skierowanego
  69.     /**for (int i = 0; i < m; i++)
  70.     {
  71.         adjMatrix[edges[i].s][edges[i].t] = 1;
  72.     }**/
  73.  
  74. }
  75.  
  76. int Graph::edgeCnt()
  77. {
  78.     int m = 0;
  79.  
  80.     //odczytuje z macierzy sasiedztwa ile jest krawedzi
  81.     for (int i = 0; i < n; i++)
  82.     {
  83.         for (int j = 0; j < n; j++)
  84.         {
  85.             if (adjMatrix[i][j] == 1)
  86.             {
  87.                 m++;
  88.             }
  89.         }
  90.     }
  91.     //teraz m dziele przez 2, bo graf jest nieskierowany
  92.     m = m / 2;
  93.  
  94.     return m;
  95. }
  96.  
  97. int Graph::nodeCnt()
  98. {
  99.     return n;
  100. }
  101.  
  102. void Graph::insertEdge(int u, int v)
  103. {
  104.     adjMatrix[u][v] = 1;
  105. }
  106.  
  107. void Graph::deleteEdge(int u, int v)
  108. {
  109.     adjMatrix[u][v] = 0;
  110. }
  111.  
  112. bool Graph::check(int u, int v)
  113. {
  114.     if (adjMatrix[u][v] == 1)
  115.         return true;
  116.     else
  117.         return false;
  118. }
  119.  
  120. void Graph::bfs(int s) //s-wezel, od ktorego rozpoczynamy przeszukiwanie grafu
  121. {
  122.     //int m = edgeCnt(); //obliczam ile jest krawedzi
  123.  
  124.     //tworze tablice przechowujaca odwiedzone wezly
  125.     int* odwiedzone = new int[n];
  126.     //wpisuje do tablicy odwiedzone 0
  127.     for (int i = 0; i < n; ++i)
  128.     {
  129.         odwiedzone[i] = 0;
  130.     }
  131.  
  132.     //wezel s ustawiam jak odwiedzony
  133.     odwiedzone[s] = 1;
  134.  
  135.     //tworze kolejke intow, to jest kolejka fifo
  136.     queue<int> kolejka;
  137.  
  138.     /**
  139.     METODY DLA BIBLIOTEKI QUEUE
  140.     push - umieszczenie nowego elementu na końcu kolejki
  141.     pop - usunięcie istniejącego elementu z początku kolejki
  142.     empty - informacja czy kolejka jest pusta
  143.     size - zwraca ilość elementów umieszczonych w kolejce
  144.     front - zwraca wartość pierwszego elementu w kolejce
  145.     back - zwraca wartość ostatniego elementu w kolejce
  146.     **/
  147.  
  148.     //dodaje do kolejki wezel s
  149.     kolejka.push(s);
  150.  
  151.     int aktualny; //pamieta pierwszy element w kolejce fifo
  152.  
  153.     while (!kolejka.empty())
  154.     {
  155.         aktualny = kolejka.front();
  156.         cout << aktualny << " ";
  157.  
  158.         for (int i = 0; i < n; ++i)
  159.         {
  160.             if ((adjMatrix[aktualny][i] == 1) && (odwiedzone[i] == 0))
  161.             {
  162.                 odwiedzone[i] = 1;
  163.                 kolejka.push(i); //dodaje i na koniec kolejki
  164.             }
  165.         }
  166.         kolejka.pop(); //usuniecie elementu z poczatku kolejki
  167.     }
  168. }
  169.  
  170. void Graph::bfs(int s, int* connectedComp, int components)
  171. {
  172.     //int m = edgeCnt(); //obliczam ile jest krawedzi
  173.  
  174.     //tworze tablice przechowujaca odwiedzone wezly
  175.     int* odwiedzone = new int[n];
  176.     //wpisuje do tablicy odwiedzone 0
  177.     for (int i = 0; i < n; ++i)
  178.     {
  179.         odwiedzone[i] = 0;
  180.     }
  181.  
  182.     //wezel s ustawiam jak odwiedzony
  183.     odwiedzone[s] = 1;
  184.  
  185.     //tworze kolejke intow, to jest kolejka fifo
  186.     queue<int> kolejka;
  187.  
  188.     /**
  189.     METODY DLA BIBLIOTEKI QUEUE
  190.     push - umieszczenie nowego elementu na końcu kolejki
  191.     pop - usunięcie istniejącego elementu z początku kolejki
  192.     empty - informacja czy kolejka jest pusta
  193.     size - zwraca ilość elementów umieszczonych w kolejce
  194.     front - zwraca wartość pierwszego elementu w kolejce
  195.     back - zwraca wartość ostatniego elementu w kolejce
  196.     **/
  197.  
  198.     //dodaje do kolejki wezel s
  199.     kolejka.push(s);
  200.  
  201.     int aktualny; //pamieta pierwszy element w kolejce fifo
  202.  
  203.     while (!kolejka.empty())
  204.     {
  205.         aktualny = kolejka.front();
  206.         if (connectedComp[aktualny] == -1)
  207.             connectedComp[aktualny] = components;
  208.  
  209.         for (int i = 0; i < n; ++i)
  210.         {
  211.             if ((adjMatrix[aktualny][i] == 1) && (odwiedzone[i] == 0))
  212.             {
  213.                 odwiedzone[i] = 1;
  214.                 kolejka.push(i); //dodaje i na koniec kolejki
  215.             }
  216.         }
  217.         kolejka.pop(); //usuniecie elementu z poczatku kolejki
  218.     }
  219. }
  220.  
  221. void Graph::dfs(int s)
  222. {
  223.     int* visited = new int[n];
  224.  
  225.     for(int i = 0; i < n; i++) {
  226.         visited[i] = -1;
  227.     }
  228.    
  229.     visit(visited, s);
  230.    
  231.     //tworze stos intow
  232.     //stack<int> stos;
  233.  
  234.     /**
  235.     METODY DLA BIBLIOTEKI <stack>
  236.     push - umieszczenie nowego elementu na szczycie stosu;
  237.     pop - zdjęcie istniejącego elementu ze szczytu stosu;
  238.     empty - informacja czy stos jest pusty;
  239.     size - zwraca ilość elementów umieszczonych na stosie;
  240.     top - zwraca wartość szczytowego elementu na stosie.
  241.     **/
  242.  
  243.     //tworze tablice odwiedzin typu bool
  244.     //bool* V = new bool[n];
  245.  
  246.     //zeruje (false) tablice odwiedzin
  247.     /**for (int i = 0; i < n; i++)
  248.     {
  249.         V[i] = false;
  250.     }**/
  251.  
  252.     //wrzucamy startujacy wierzcholek na stos
  253.     //stos.push(s);
  254.  
  255.     /**while (!stos.empty())
  256.     {
  257.         s = stos.top();
  258.         //usuwamy odwiedzany element
  259.         stos.pop();
  260.  
  261.         cout << s << " ";
  262.  
  263.         V[s] = true;
  264.  
  265.         for (int j = n - 1; j >= 0; --j)
  266.         {
  267.             if (adjMatrix[j][s] != 0 && V[j] == false)
  268.             {
  269.                 //wrzucamy na stos jego sasiadow
  270.                 stos.push(j);
  271.                 V[j] = true;//Znaznaczamy ,że go odwiedzimy!(w niedalekiej przyszłości)
  272.                 //Inaczej będziemy mieli np taką sytuację w stosie 2,3,4,2 <-- 2x dwójka
  273.             }
  274.         }
  275.     }**/
  276. }
  277.  
  278. void Graph::visit(int *visited, int u) {
  279.     visited[u] = 0;
  280.     cout << u << " ";
  281.  
  282.     for(int v = 0; v < n; v++) {
  283. //      if (adjMatrix[u][v] == 0) {
  284. //          continue;
  285. //      }
  286.         if (visited[v] == -1)
  287.         {
  288.             visit(visited, v);
  289.         }
  290.     }
  291.     visited[u] = 1;
  292. }
  293.  
  294. int* Graph::connectedComponents()
  295. {
  296.     int* connectedComp = new int[n];
  297.  
  298.     for(int i = 0; i < n; i++) {
  299.         connectedComp[i] = -1;
  300.     }
  301.  
  302.     int components = 0;
  303.     for(int i = 0; i < n; i++) {
  304.         if(connectedComp[i] == -1) {
  305.             bfs(i, connectedComp, components);
  306.             components++;
  307.         }
  308.     }
  309.     return connectedComp;
  310. }
  311.  
  312. int* Graph::Dijkstra(int s)
  313. {
  314.     int* q = new int[n]; //zawiera wezly
  315.     vector<int> v; //zawiera wezly, dla ktorych juz obliczono najkrotsza sciezke s
  316.     int* d = new int[n]; //tablica kosztow
  317.     int* p = new int[n]; //tablica poprzednikow
  318.     int min, index, amount = n;
  319.     //inicjalizacja tablic
  320.     for (int i = 0; i < n; i++)
  321.     {
  322.         q[i] = i;
  323.         d[i] = INT_MAX - 200; //najpierw ustawiamy ja na nieskonczonosc
  324.         p[i] = -1;
  325.     }
  326.     d[s] = 0; //koszt dla wierzcholka startowego ustawiamy na 0
  327.     while (amount > 0)
  328.     {
  329.         min = INT_MAX - 200;
  330.         for (int i = 0; i < n; i++)
  331.         {
  332.             if (q[i] != -1 && min > d[i])
  333.             {
  334.                 min = d[i];
  335.                 index = i;
  336.             }
  337.         }
  338.         v.push_back(q[index]);
  339.         q[index] = -1;
  340.         amount--;
  341.         for (int i = 0; i < n; i++)
  342.         {
  343.             if (check(index, i) && q[i] != -1)
  344.             {
  345.                 if (d[i] > d[index] + adjMatrix[index][i])
  346.                 {
  347.                     d[i] = d[index] + adjMatrix[index][i];
  348.                     p[i] = index;
  349.                 }
  350.             }
  351.         }
  352.     }
  353.  
  354.     return d;
  355.  
  356.     /**for (int i = 0; i < n; i++)
  357.     {
  358.         cout << i << "\t";
  359.     }
  360.     cout << endl;**/
  361.     /**for (int i = 0; i < n; i++)
  362.     {
  363.         cout << d[i] << "\t";
  364.     }
  365.     cout << endl;**/
  366.     /**for (int i = 0; i < n; i++)
  367.     {
  368.         cout << p[i] << "\t";
  369.     }
  370.     cout << endl;**/
  371.    
  372.     /**int* d = new int[nodeCnt()]; //tablica kosztow
  373.     int* p = new int[nodeCnt()]; //tablica poprzednikow
  374.     bool* QS = new bool[nodeCnt()]; //zawiera true, jesli dla wierzcholka obliczono najkrotsza sciezke od s
  375.     int* S = new int[nodeCnt()]; //zawiera wezly dla, ktorych obliczono najkrotsza sciezke od s, stos
  376.     int sptr = 0; //wskaznik stosu
  377.    
  378.     //inicjujemy tablice
  379.     for (int i = 0; i < n; i++)
  380.     {
  381.         d[i] = INT_MAX; //ustawiamy na nieskonczonosc
  382.         p[i] = -1;
  383.         QS[i] = false;
  384.     }
  385.  
  386.     d[s] = 0; //koszt dojscia s jest zerowy**/
  387.  
  388.  
  389. }
  390.  
  391. /**vector<int> Graph::path(int s, int e)
  392. {
  393.     vector<int> wynik;
  394.     vector<int> temp;
  395.  
  396.     int** dane;
  397.  
  398.     dane = Dijkstra(s);
  399.     int x = e;
  400.     temp.push_back(e);
  401.  
  402.     while (x != s) {
  403.         x = dane[1][x];
  404.         temp.push_back(x);
  405.     }
  406.  
  407.  
  408.     for (int i = 0, j = temp.size() - 1; i < temp.size(); i++, j--) {
  409.         wynik.push_back(temp[j]);
  410.     }
  411.  
  412.     cout << endl << "Najkrotsza droga wynosi " << dane[0][e] << endl;
  413.     for (size_t i = 0; i < wynik.size(); i++)
  414.     {
  415.         cout << wynik[i] << " ";
  416.     }
  417.  
  418.     return wynik;
  419. }**/
  420.  
  421. ostream& operator<<(ostream& out, Graph& g)
  422. {
  423.     for (int i = 0; i < g.nodeCnt(); i++)
  424.     {
  425.         for (int j = 0; j < g.nodeCnt(); j++)
  426.         {
  427.             out << "[" << i << "]" << "[" << j << "] " << g.adjMatrix[i][j] << endl;
  428.         }
  429.     }
  430.  
  431.     return out;
  432. }
  433.  
  434. int main(int argc, char** argv)
  435. {
  436.     //WYDAJE MI SIE, ZE ZLE DZIALA DFS DLA GRAFU SKIEROWANEGO, ALE NIE WIEM
  437.    
  438.     //int n = 10, m = 14; //dla grafu nieskierowanego
  439.     int n = 10, m = 13; //dla grafu skierowanego
  440.     edge undirectedConnectedGraph[] = { {0,1}, {0,4}, {0,6}, {1,2}, {1,7}, {2,3}, {2,8}, {3,5}, {3,9}, {4,7}, {5,8}, {6,7}, {7,8}, {8,9} };
  441.     //edge directedConnectedGraph[] = { {0,1}, {1,2}, {1,7}, {2,8}, {3,2}, {3,9}, {4,0}, {5,3}, {6,0}, {7,4}, {7,6}, {8,5}, {9,8} };
  442.     Graph g(n, m, undirectedConnectedGraph);
  443.     //Graph g(n, m, directedConnectedGraph);
  444.     cout << g;
  445.  
  446.     g.deleteEdge(1, 2);
  447.     g.deleteEdge(7, 8);
  448.  
  449.     g.bfs(0);
  450.     g.bfs(2);
  451.  
  452.     int* tab;
  453.     tab = g.connectedComponents();
  454.     cout << endl;
  455.     for (int i = 0; i < n; i++) {
  456.         cout << tab[i] << " ";
  457.     }
  458.     cout << endl;
  459.     //g.bfs(0);
  460.     //cout << endl;
  461.     //g.dfs(0);
  462.  
  463.  
  464.     return 0;
  465. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement