// ==================================================================
// Auteur : Jean-Michel RICHER
// Email : jean-michel.richer@univ-angers.fr
// Institution : Université d'Angers, Faculté des Sciences
// Département : Informatique
// ==================================================================
//
// Objectif : Implantation itérative de liste simplement chaînée
// concernant des personnes
//
// Spécificité : On passe en paramètre des sous-programmes qui
// agissent sur les listes, la liste à modifier. Pour les sous-
// programmes qui modifie la liste (comme l'ajout d'un élément)
// on retourne la tête de la nouvelle liste modifiée.
//
// Lors de l'appel de ces sous-programmes il faut donc passer
// la liste en paramètre mais éventuellement récupérer la liste
// modifiée
//
// L'implantation donnée ici utilise des macro-instructions afin
// de rendre la lecture du code plus aisée.
// ==================================================================
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// ==================================================================
// structures communes
// ==================================================================
struct personne
{
string nom, prenom;
};
// Instanciation d'une personne
void personne_initialiser(personne &p, string nom, string prenom)
{
p.nom = nom;
p.prenom = prenom;
}
// Redéfinition de l'opérateur de sortie sur un flux : il est nécessaire
// de redéfinir cet opérateur car il est utilisé pour l'affichage
ostream &operator<<(ostream &out, personne &p)
{
out << "(" << p.nom << ", " << p.prenom << ")";
return out;
}
// Redéfinition de l'opérateur de comparison > : il est nécessaire
// de redéfinir cet opérateur car il est utilisé pour le tri
// Note : on compare les personnes suivant leur nom uniquement
bool operator>(const personne &p1, const personne &p2)
{
return p1.nom > p2.nom;
}
// définition du type de la valeur stockée par un élément de la liste
using type_valeur = personne;
// définition d'un élément (maillon) de la liste
struct type_element_de_liste
{
// pointeur sur l'élément suivant
type_element_de_liste *suivant;
// valeur stockée par cet élément
type_valeur valeur;
};
// définition d'une liste comme un pointeur sur un élément
using liste = type_element_de_liste *;
// définition de la liste vide
const liste liste_vide = nullptr;
// ==================================================================
// structures spécifiques à cette implantation
// ==================================================================
#define le_suivant_de(l) l->suivant
#define la_valeur_de(l) l->valeur
// ==================================================================
// Sous-programmes qui agissent sur une liste
// ==================================================================
// Initialisation de la liste
liste liste_initialiser()
{
return liste_vide;
}
// Ajout en tête de la liste
liste liste_ajouter_en_tete(liste l, type_valeur valeur)
{
type_element_de_liste *nouvel_element = new type_element_de_liste;
le_suivant_de(nouvel_element) = l;
la_valeur_de(nouvel_element) = valeur;
return nouvel_element;
}
// Ajout en queue de la liste
liste liste_ajouter_en_queue(liste l, type_valeur valeur)
{
type_element_de_liste *nouvel_element = new type_element_de_liste;
le_suivant_de(nouvel_element) = liste_vide;
la_valeur_de(nouvel_element) = valeur;
if (l == liste_vide)
{
return nouvel_element;
}
else
{
// rechercher le dernier élément
liste dernier = l;
while (le_suivant_de(dernier) != liste_vide)
{
dernier = le_suivant_de(dernier);
}
le_suivant_de(dernier) = nouvel_element;
return l;
}
}
// Affichage de la liste
void liste_afficher(liste l)
{
liste courant = l;
while (courant != liste_vide)
{
cout << la_valeur_de(courant) << " ";
courant = le_suivant_de(courant);
}
cout << endl;
}
// Tri de la liste sous forme de tri à bulle
void liste_trier(liste l)
{
liste courant1 = l;
while (courant1 != liste_vide)
{
liste courant2 = le_suivant_de(courant1);
while (courant2 != liste_vide)
{
if (la_valeur_de(courant1) > la_valeur_de(courant2))
{
swap(la_valeur_de(courant1), la_valeur_de(courant2));
}
courant2 = le_suivant_de(courant2);
}
courant1 = le_suivant_de(courant1);
}
}
// ==================================================================
// Programme principal
// ==================================================================
// On insère des élément dans la liste (en tête, puis en queue) et
// on affiche le résultat : 11 4 3 2 1 5 6 7 8 9 10 -1
// on tri ensuite la liste : -1 1 2 3 4 5 6 7 8 9 10 11
// ==================================================================
int main()
{
liste l;
personne p;
l = liste_initialiser();
std::vector<pair<string, string>> identites = {
{"dupond", "jean"},
{"dupont", "jean"},
{"decafer", "marc"},
{"naymar", "jean"},
{"nade", "marie"},
{"estone", "charles"}};
for (auto paire : identites)
{
personne_initialiser(p, paire.first, paire.second);
l = liste_ajouter_en_tete(l, p);
}
cout << "liste initiale = ";
liste_afficher(l);
liste_trier(l);
cout << "liste triée = ";
liste_afficher(l);
return EXIT_SUCCESS;
}