//  Eine Adjazenliste, beeinflußt von Boost::Graph, std::vector und std::liste.
//  Effizienz gegenüber reinem  C wird mal genessen.

#include <iostream>
#include <vector>
#include <list>



// Klasse zur Repräsentation des Graphen
class Graph {
public:
    //  gerichtet oder ungerichtet, für void kanteHinzufuegen.
    enum GraphTyp { none, gerichtet, ungerichtet };

private:
   
    int anzahlKnoten;
    GraphTyp t;

    // Ein Array/Vector von Listen. Jedes Element im Vector repräsentiert einen Knoten.
    // Die Liste enth&auml;lt alle benachbarten Knoten.
    std::vector<std::list<int>> adjazenzListe;
     
public:
    
    // Konstruktor initialisiert den Graph mit der gewünschten Anzahl an Knoten
    Graph(int knoten) {
        anzahlKnoten = knoten;
        adjazenzListe.resize(knoten);
        t = none;
    }

    void setOption(GraphTyp t)
    {
        this->t = t;
    }

    // Methode zum Hinzufügen einer Kante (ungerichteter Graph)
    void kanteHinzufuegen(int start, int ziel) {
        // Kante von Start zu Ziel
        adjazenzListe[start].push_back(ziel);

        if  ( t ==  ungerichtet || t == none)
        adjazenzListe[ziel].push_back(start);
    }

    // Methode zur Ausgabe der Adjazenzliste auf der Konsole
    void ausgeben() {
        for (int i = 0; i < anzahlKnoten; ++i) {
            std::cout << "Knoten " << i << " ist verbunden mit: ";
            for (int nachbar : adjazenzListe[i]) {
                std::cout << nachbar << " ";
            }
            std::cout << "\n";
        }
    }
};

int main() {
    // Erstellt einen Graphen mit 5 Knoten (ID 0 bis 4)
    Graph g(5);
    Graph::GraphTyp t =  Graph::ungerichtet;
    g.setOption(t);
    // Beliebige Anzahl von Kanten hinzufügen
    g.kanteHinzufuegen(0, 1);
    g.kanteHinzufuegen(0, 4);
    g.kanteHinzufuegen(1, 2);
    g.kanteHinzufuegen(1, 3);
    g.kanteHinzufuegen(1, 4);
    g.kanteHinzufuegen(2, 3);
    g.kanteHinzufuegen(3, 4);
    

    // Graph anzeigen
    g.ausgeben();

    return 0;
}
