Академический Документы
Профессиональный Документы
Культура Документы
En utilisant les nouvelles conventions et possibilités du C++ en particulier le passage d’argument par
référence, l’affichage à l’aide de l’opérateur de flux
1) Ecrire une structure point de dimension 3 et une fonction affichant les coordonnées d’un point sous la
forme : (x, y, z) et écrire une fonction de comparaison de deux points.
2) On souhaite gérer des listes de points de taille quelconque avec les possibilités suivantes :
Une liste sera une structure contenant un tableau de pointeur sur des points (Points), le nombre de points
(nb points) et le nombre maximal de points (max points) : la taille du tableau. On aura besoin d’une
fonction resize pour augmenter la taille du tableau si besoin.
3) Faire une liste avec les mêmes fonctionnalités ne s’appuyant pas sur un tableau mais sur un chaı̂nage
des points. On ne considérera que le chaı̂nage sur le point suivant en ajoutant à la structure de point un
pointeur sur le point suivant (next) qui est NULL si c’est le dernier!
4) Comparer les vitesses d’exécution de add et remove en utilisant la fonction time() définie dans time.h
time t t1=time(NULL);
bloc de programme
time t t2=time(NULL);
t2-t1 contient le temps d’éxécution en seconde du bloc de code. Attention prévoyez un nombre conséquent
d’opérations, au besoin faire une boucle autour d’un même calcul, afin que le temps soit significatif (plusieurs
secondes).
5) Ecrire la fusion de deux listes de points (produit une nouvelle liste) en prévoyant l’élimination des doublons
(union stricte)
1
Correction
//===========================================================================
// TP1 Programmation Scientifique mars 2005
//===========================================================================
// structure point (3D)
// structure liste_points (tableau de pointeurs de point)
// structure liste_chaine_points (chainage "suivant")
//
// fonctionnalités :
//
// point : affichage et comparaison de deux points
// liste : initialisation et réinitialisation de la liste
// affichage de la liste
// ajout, suprresion d’un point de la liste
// appartenance d’un point à la liste
// fusion de listes sans doublon (union)
//
//===========================================================================
//définition système
//------------------
#include <time.h>
#include <iostream>
#include <algorithm>
#include <fstream>
//variable globale
//----------------
ofstream out;
//===========================================================================
//structure Point (dimension 3)
//===========================================================================
struct point
{float x,y,z; //coordonnées des points
point * next; //pointeur sur le point suivant (liste chain\’{e}e)
};
//===========================================================================
//liste de points (à l’aide d’un tableau)
//===========================================================================
struct liste_points
{int nb_points; //nombre de points
int max_points; //nombre maximum de points
point ** Points; //pointeur sur un tableau de pointeur de points
};
//libération mémoire
//------------------
void reset(liste_points & L)
{for(int i=0;i<L.nb_points;i++) delete L.Points[i]; //suppression des points
delete [] L.Points; //suppression du tableau
L.nb_points=0;
2
L.max_points=0;
}
//Redimensionnement
//-----------------
void resize(liste_points & L,int n)
{//création d’une nouvelle liste
point** newliste=new point*[n];
//recopie
for(int i=0;i<L.nb_points;i++) newliste[i]=L.Points[i];
L.max_points=n;
L.nb_points=min(L.nb_points,L.max_points);
delete [] L.Points;
L.Points=newliste;
}
//Affichage de la liste
//---------------------
void print(const liste_points & L)
{for(int i=0;i<L.nb_points;i++) print(*L.Points[i]);
}
//===========================================================================
//liste chainée de points
//===========================================================================
struct liste_chaine_points
{int nb_points; //nombre de points
point *first; //pointeur sur le premier point de la liste
3
point *last; //pointeur sur le dernier point de la liste
};
//libération mémoire
//------------------
void reset(liste_chaine_points & L)
{point *P=L.first; //pointeur sur le premier point de la liste
point *Q=P;
while(P!=NULL) {Q=P->next;delete P;P=Q;}
init(L);
}
4
//fusion de deux listes de points (non trié : tres couteux O(nm))
//---------------------------------------------------------------
liste_chaine_points merge(const liste_chaine_points & L1,const liste_chaine_points & L2)
{//nouvelle liste
liste_chaine_points L12;init(L12);
point *P=L1.first;
for(int i=0;i<L1.nb_points;i++) //recopie de L1
{point *Q=new point(*P); //création d’une copie du point
add(L12,*Q);
P=P->next;
}
P=L2.first;
for(int i=0;i<L2.nb_points;i++) //ajout de L2
{if(in_liste(L1,*P)==-1)
{point *Q=new point(*P); //création d’une copie du point
add(L12,*Q);
}
P=P->next;
}
return L12;
}
//===========================================================================
//programme principal
//===========================================================================
int main()
{//fichier de sortie
//-----------------
out.open("out");
//test de fusion
liste_points L12=merge(L1,L2);
out<<"liste de points L12 "<<endl;
print(L12);
5
{remove(L12,U);
}
tf=time(NULL);
out<<"temps calcul remove liste = "<<100*(tf-t0)<<endl;
//test de fusion
liste_chaine_points LC12=merge(LC1,LC2);
out<<"liste de points LC12"<<endl;
print(LC12);
out.close();
cout<<"programme terminé ....";
system("PAUSE");
return 0;
}
//---------------------------------------------------------------------------
Remarques:
• lors de l’ajout d’un point on fait systématiquement une recopie du point et non une affectation du
pointeur du point car ce dernier pourrait être supprimé par ailleurs laissant ainsi un pointeur ne
pointant plus sur rien. Seule la liste a le contrôle des copies des points, ils ne peuvent donc pas être
détruit par inadvertance.
• la suppression d’un point est une opération couteuse car il faut rechercher le point dans une liste non
triée (recherche séquentielle en O(n)!)
• il n’est pas possible de faire un tableau de références sur des points au lieu d’un tableau de pointeurs
sur des points, car on ne peut pas initialiser une référence vide. Une référence est un alias sur un
pointeur qui doit exister.
• on verra plus tard que le C++ (STL) propose des structures vector et list permettant de faire des
liste de points sans aucun effort et dont l’implémentation est optimisée!
6
Résultats
points O A B C :
(0,0,0)
(1,1,1)
(1,0,0)
(1,1,1)
liste de points L1
(0,0,0)
(1,1,1)
(1,0,0)
liste de points L2
(1,1,1)
(2,2,2)
liste de points L12
(0,0,0)
(1,1,1)
(1,0,0)
(2,2,2)
temps calcul add liste = 500
temps calcul remove liste = 4000
liste de points LC1
(0,0,0)
(1,1,1)
(1,0,0)
liste de points LC2
(1,1,1)
(2,2,2)
liste de points LC12
(0,0,0)
(1,1,1)
(1,0,0)
(2,2,2)
temps calcul add liste chainée = 2
temps calcul remove liste chainée = 1
On notera que l”utilisation d’un tableau est extrêmement pénalisant (jusqu’à 4000 fois plus couteux pour les
opérations de suppression). Cela est du au fait que l’on doit à chaque suppression décaler tous les ééments du
tableau. C’est d’autant plus pénalisant que le tableau est tres gros (100000 éléments) et que l’on supprime à
chaque fois le premier élément induisant de fait la translation de tout le tableau (c’est la pire des situations!).
La suppression ainsi que l’ajout d’un élément d’une liste chainée (hormis la recherche du point dans la liste)
est insensible à la dimension du tableau.