1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
#ifndef GRAPHE_LISTE_HPP_
#define GRAPHE_LISTE_HPP_
/* Classe GrapheListe
*
* Cette classe implante un graphe avec des listes d'adjacences. Le poids est générique.
* Pour implanter un graphe non valué il suffit de l'instancier avec des booléens.
*
*
*
*
*/
#include <vector>
#include <list>
#include <utility>
#include <stdexcept>
template <typename Poids>
class GrapheListe {
public:
// Constructeur
GrapheListe(const bool oriente, const Poids& infini);
// Destructeur
~GrapheListe();
// ajoute un sommet au graphe. Retourne l'identificateur du sommet
const unsigned int ajouterSommet();
// Retourne vrai si on peut aller de s1 Ã s2
const bool sontAdjacents(const unsigned int s1, const unsigned int s2) const;
// Retourne le poids de s1 Ã s2
const Poids& getPoids(const unsigned int s1, const unsigned int s2) const;
// retourne tous les voisins du sommet s1. La liste passée en paramètre est intialement
// vidée
void sommetsAdjacents(const unsigned int s1, std::list<unsigned int>& sommets) const;
// Ajoute un arc de s1 Ã s2
void ajouterArc(const unsigned int s1, const unsigned int s2, const Poids& unPoids);
// Retire l'arc entre s1 et s2
void retirerArc(const unsigned int s1, const unsigned int s2);
// Retourne le nombre de sommets du graphe
const unsigned int getNbSommets() const {return m_nbSommets;}
private:
typedef std::pair<unsigned int, Poids> t_arc; // un arc comprend un idnetificateur de sommet et un poids
typedef std::list<t_arc> t_listeAdjacence; // une liste d'arcs
typedef std::vector<t_listeAdjacence> t_graphe; // Le graphe est un vecteur de listes d'adjacences
// Fonction qui permet de valider l'existence d'un sommet.
bool verifierSommet(const unsigned int s) const;
// insere un arc dans la liste d'adjacence de s1
void insererArc(const unsigned int s1, const unsigned int s2, const Poids& unPoids);
// retire un arc de la liste d'adjacence de s1
void enleverArc(const unsigned int s1, const unsigned int s2);
unsigned int m_nbSommets; // le nombre de sommets
const bool m_oriente; // vrai si le graphe est oriente
t_graphe m_graphe; // le graphe
const Poids& m_infini; // Représente une valeur signifiant que ça ne passe pas entre deux sommets
};
/* Implantation de la classe */
template <typename Poids>
GrapheListe<Poids>::GrapheListe(const bool oriente, const Poids& infini) :
m_nbSommets(0),
m_oriente(oriente),
m_infini(infini)
{
}
template <typename Poids>
GrapheListe<Poids>::~GrapheListe()
{
}
template <typename Poids>
const unsigned int GrapheListe<Poids>::ajouterSommet()
{
m_graphe.push_back(t_listeAdjacence());
m_nbSommets++;
return m_graphe.size() - 1;
}
template <typename Poids>
const bool GrapheListe<Poids>::sontAdjacents(const unsigned int s1, const unsigned int s2) const {
return getPoids(s1, s2) != m_infini;
}
template <typename Poids>
const Poids& GrapheListe<Poids>::getPoids(const unsigned int s1, const unsigned int s2) const
{
if (! verifierSommet(s1) || ! verifierSommet(s2)) {
throw std::runtime_error("Sommet invalide!");
}
const t_listeAdjacence& liste = m_graphe.at(s1);
typename t_listeAdjacence::const_iterator iter = liste.begin();
// La liste est triée, il suffit de parcourir jusqu'au premier qui n'est pas plus petit
while (iter != liste.end() && iter->first < s2) {
iter++;
}
// vérifie si on a trouvé le sommet
if (iter == liste.end() || iter->first != s2) {
return m_infini;
}
return iter->second;
}
template <typename Poids>
void GrapheListe<Poids>::sommetsAdjacents(const unsigned int s1, std::list<unsigned int>& sommets) const
{
if (! verifierSommet(s1)) {
throw std::runtime_error("Sommet invalide!");
}
sommets.clear();
// On insère tous les sommets de la liste
const t_listeAdjacence& liste = m_graphe.at(s1);
typename t_listeAdjacence::const_iterator iter = liste.begin();
while (iter != liste.end()) {
sommets.push_back(iter->first);
iter++;
}
}
template <typename Poids>
void GrapheListe<Poids>::ajouterArc(const unsigned int s1, const unsigned int s2, const Poids& unPoids) {
if (! verifierSommet(s1) || ! verifierSommet(s2)) {
throw std::runtime_error("Sommet invalide");
}
insererArc(s1, s2, unPoids);
// Il ne faut pas oublier de l'ajouter dans l'autre sens également
if (! m_oriente) {
insererArc(s2, s1, unPoids);
}
}
template <typename Poids>
void GrapheListe<Poids>::insererArc(const unsigned int s1, const unsigned int s2, const Poids& unPoids) {
if (! verifierSommet(s1) || ! verifierSommet(s2)) {
throw std::runtime_error("Sommet invalide");
}
t_listeAdjacence& liste = m_graphe.at(s1);
typename t_listeAdjacence::iterator iter = liste.begin();
while (iter != liste.end() && iter->first < s2) {
iter++;
}
// Ici on est sur le premier qui n'est pas plus petit.
if (iter == liste.end() || iter->first > s2) {
liste.insert(iter, t_arc(s2, unPoids));
} else {
iter->second = unPoids;
}
}
template <typename Poids>
void GrapheListe<Poids>::retirerArc(const unsigned int s1, const unsigned int s2) {
if (! verifierSommet(s1) || ! verifierSommet(s2)) {
throw std::runtime_error("Sommet invalide");
}
enleverArc(s1, s2);
// Il ne faut pas oublier de le retirer dans l'autre sens également
if (! m_oriente) {
enleverArc(s2, s1);
}
}
template <typename Poids>
void GrapheListe<Poids>::enleverArc(const unsigned int s1, const unsigned int s2){
t_listeAdjacence& liste = m_graphe.at(s1);
typename t_listeAdjacence::iterator iter = liste.begin();
while (iter != liste.end() && iter->first < s2) {
iter++;
}
// Ici on est sur le premier qui n'est pas plus petit.
if (iter != liste.end() && iter->first == s2) {
liste.erase(iter);
}
}
template <typename Poids>
bool GrapheListe<Poids>::verifierSommet(const unsigned int s) const
{
return s >= 0 && s < m_graphe.size();
}
#endif |
Partager