OVH Cloud OVH Cloud

std::set

23 réponses
Avatar
Nicolas Aunai
salut,

je suis en train d'apprendre les conteneurs de la stl, et dans quel cas
utiliser l'un plutôt que l'autre... j'ai un petit problème a vous
soumettre.

Disons que j'ai un objet A qui contient un string et un ensemble
ordonné de pointeurs sur des objets A.

pour cet ensemble ordonné, j'utilise std::set, qui me permet d'ajouter
des éléments qui sont inséré directement au bon endroit selon la
relation d'ordre définie pour A.

maintenant j'ai quelques problèmes :

class MaString
{
public:
string s;
set<const MaString *> tab;


MaString(const string &str);
void MiseAJour(const vector<MaString> &);
static void maj(vector<MaString> &);
bool operator<(const MaString &ms) const;
friend ostream & operator<<(ostream &os,const MaString &ms);
};

le vector<MaString> pris en argument par MiseAjour contient tout un tas
d'objet MaString non ordonnés, dont l'objet en cours lui même, et le
set de l'objet, doit se remplir avec les pointeurs vers les autres
objets du vector, sauf bien sûr le pointeur sur lui même. Et les
pointeurs doivent etre rangés selon la relation d'ordre de MaString.

(la relation d'ordre de MaString est tout simplement l'opérateur '<' de
son membre string)

j'ai essayé ceci :

void
MaString::MiseAJour(const vector<MaString> &s)
{
vector<MaString>::const_iterator iter_s = s.begin();

while(iter_s != s.end())
{
if(&*iter_s != this)
tab.insert(&*iter_s);
}
}


je n'ai pas l'impression que ça marche correctement, de plus, la
méthode 'insert' doit renvoyer un objet 'pair<iterator,bool>' indiquant
si l'insertion a bien eu lieu, si j'ai bien compris. Mais je pige pas
trop ce qu'est cet objet, ni comment le déclarer pour vérifier le
retour de insert.


maintenant autre question, les set ne disposent pas de l'opérateur []
pour accéder a un de leurs membres, ou alors j'ai pas vu pas
compris...? donc le moyen pour aller sur un objet d'un set et
l'iterateur... je m'en sert pour ma surcharge d'affichage de mon objet
MaString, mais apparement j'ai une faute sur l'iterator, et je
comprends pas


ostream &
operator<<(ostream &os,const MaString &ms)
{
set<const MaString*>::const_iterator i = ms.tab.begin();

os << "String = " << ms.s << endl << endl;

os << "Mes Voisins ( "<< ms.tab.size() << " ): " << endl;
os << "============= " << endl << endl;

while(i != ms.tab.end())
{
os << " - "<< *i->s << endl;
i ++;
}
os << endl;

return os;
}

--
Nico,
http://astrosurf.com/nicoastro
messenger : nicolas_aunai@hotmail.com

3 réponses

1 2 3
Avatar
Nicolas Aunai
Falk Tannhäuser a émis l'idée suivante :


En mettant
s3.AjouterCluster(Cluster(1,2,10));
s3.AjouterCluster(Cluster(-4,5,8));
s3.AjouterCluster(Cluster(0,0,0));
dans ton 'main', le programme m?affiche
[...]
cluster 2 : ======================================= > Position : [ 0, 0, 0 ] barycentre : [ 0, 0, 0 ] Generation : 1
Mes fils : ---------- Mes influences : ---------------- -Position : [ 1, 2,
10 ] D = 10.25
======================================== >
(absence de "-Position : [ -4, 5, 8 ] D = 10.25" ; je ne sais pas si c?est
important ou pas pour ce que tu veux faire - sinon voir 'std::multiset')



en effet pour le moment j'ai fait exprès d'avoir ça. je fais petit à
petit, une difficulté à la fois.



Le problème vient du fait que 'std::vector' a besoin du constructeur de
copie et de l?opérateur d?affectation, et ta classe 'Cluster' utilise
les opérations générées par le compilateur qui ne marchent pas bien parce
que le champ ?Influences? aura un functeur de comparaison pointant sur
le 'Cluster' d?origine plutôt que l?objet courant. Par conséquent,
les distances à l?insertion sont calculées par rapport à ce premier...
En mettant

Cluster::Cluster(Cluster const& c)
: Position(c.Position),
Influences(c.Influences.begin(), c.Influences.end(),
CompareDistance(*this)),
Parent(c.Parent),
Generation(c.Generation)
{
}

Cluster& Cluster::operator=(Cluster const& c)
{
Position = c.Position;
Influences.clear();
Influences.insert(c.Influences.begin(), c.Influences.end());
Parent = c.Parent;
Generation = c.Generation;
return *this;
}

cela se passe mieux.



ah je me suis douté hier que l'erreur devait venir du vector et de ce
'this'... mais j'ai un peu de mal à vraiment comprendre l'affaire.. car
dans http://nicolas.aunai.free.fr/particule/points/ok j'utilise aussi
un vector et pourtant apparement ça marche très bien donc je vois pas
pk.


Reste la question si la classe 'Cluster' doit réellement avoir une sémantique
de valeur ou s?il faut en interdire les opérations de copie (ce qui
obligerait
entre autres de remplacer 'std::vector<Cluster>' par
'std::vector<Cluster*>').



qu'entends tu par "semantique de valeur" ?

--
Nico,
http://astrosurf.com/nicoastro
messenger :

Avatar
Nicolas Aunai
Franck Branjonneau a exposé le 25/02/2004 :


Une autre solution, qui évite le constructeur de copie et l'opérateur
d'affectation est de modifier CompareDistance pour ne garder que
l'information utile :

class CompareDistance
{
private:
// const Cluster *p;
V3D position_;

public:
CompareDistance(const Cluster &c);
bool operator()(const Cluster *c1, const Cluster *c2) const;
};



c'est vrai mais plus tard, la position changera aussi beaucoup au cours
du temps alors je sais pas si ça pourra poser des problèmes... et
j'aime pas trop l'idée de répéter un champ comme ça :)


Le main() de Nicolas est en O(n^2 ln n) ou n est la taille d'un
std::vector<Cluster>. N'est-ce pas un début de réponse ?


hum, un peu HS mais comment tu fais pour calculer ce 0(n^2ln(n)) ?
c'est pas super super comme complexité ça....

--
Nico,
http://astrosurf.com/nicoastro
messenger :

Avatar
Franck Branjonneau
Nicolas Aunai écrivait:

Franck Branjonneau a exposé le 25/02/2004 :

Le main() de Nicolas est en O(n^2 ln n) ou n est la taille d'un
std::vector<Cluster>. N'est-ce pas un début de réponse ?


hum, un peu HS mais comment tu fais pour calculer ce 0(n^2ln(n)) ?
c'est pas super super comme complexité ça....


main:
Pour chaque cluster -- n fois
Construire une suite ordonnée des n-1 clusters

Construire une suite ordonnée des n-1 clusters:
Insérerer un cluster dans un suite de longueur p -- ln p
ln 1 + ln 2 + ln 3 + ... + ln n est équivalent à n ln n
--
Franck Branjonneau


1 2 3