2010-12-16 474 views
3

Je sais que cela peut être une question idiote. mais j'ai encore une confusion. W.r.t std :: carte. J'ai écrit un prédicat personnalisé pour la commande dymanic de carte,STL std :: carte de commande dynamique

enum OrderingType 
{ 
    ASCENDING, 
    DESCENDING 
}; 

template <class T> 
class Ordering 
{ 
    OrderingType m_order; 

public: 
    Ordering(OrderingType order) : m_order(order) { } 

    bool operator() (const T &obj1, const T &obj2) 
    { 
     if(m_order == ASCENDING) 
      return obj1 < obj2; 

     if(m_order == DESCENDING) 
      return obj1 > obj2; 
    } 
}; 

Advantage est

  1. Nous pouvons décider de l'ordre des éléments de données dans la carte de certaines conditions

    type OrderType = (condition? ASCENDING: DESCENDING); CUSTOMMAP m (type);

  2. Nous pouvons utiliser le même pour les deux iterator avant ascendant & descendant carte commandée

    dans le code ci-dessous. la commande de la carte fonctionne bien dans les deux ordres ascendants & décroissant (amp1 & map2). Mais en assignant map2 = map1, l'ordre de map2 change avec le contenu. Je devais copier uniquement le contenu, pas le changement dans la commande. d'autres insertions sur map2 (qui a été déclaré descendant) seront dans l'ordre croissant.

Une idée ou une suggestion? ou définir un prédicat de commande bidirectionnel pour une carte est une mauvaise idée ..?

typedef map<int, int, Ordering<int> > CUSTOMMAP; 
typedef CUSTOMMAP::iterator  CUSTOMMAP_ITER; 
typedef CUSTOMMAP::const_iterator CUSTOMMAP_CONST_ITER; 

ostream& operator <<(ostream& out, const CUSTOMMAP& mapobj) 
{ 
    CUSTOMMAP_CONST_ITER citer = mapobj.begin(); 
    for(; citer != mapobj.end(); ++citer) 
    { 
     out << citer->first << " " << citer->second << endl; 
    } 
    out << "==========" << endl; 
    return out; 
} 

int main() 
{ 
    CUSTOMMAP map1(ASCENDING);  //instantiate a map with ascending sorting 
    CUSTOMMAP map2(DESCENDING); //instantiate a map with descending sorting 

    map1.insert(make_pair(1, 0)); 
    map1.insert(make_pair(2, 0)); 
    cout << map1;     // prints data in ascnding manner 

    map2.insert(make_pair(5, 0)); 
    map2.insert(make_pair(6, 0)); 
    cout << map2;     // prints data in descending manner 

    map2 = map1; 

    cout << map2;     //copys contents of map1 to map2 & changes 
            //map2's ordering predicate 
    return 0; 
} 

Répondre

5

réglage bien map2 = map1 va en fait copier l'objet entier, pas seulement les éléments. Ce que vous voulez sans doute faire alors est

map2.clear(); 
map2.insert(map1.begin(), map1.end()); 

Je crois du haut de ma tête que la complexité des deux étapes ensemble va être O(n log n), mais ne me citez pas là-dessus.

Modifier

Encore mieux (O(n)):

map2.clear(); 
map2.insert(map1.rbegin(), map1.rend()); 

« Pour la troisième version (insert (premier, dernier)), Nlog (taille + N) en général (où N est la distance entre le premier et le dernier, et la taille de la taille du conteneur avant l'insertion), mais linéaire si les éléments entre le premier et le dernier sont déjà triés selon le même critère d'ordre utilisé par le conteneur. " (http://cplusplus.com/reference/stl/map/insert)

+0

Bon point dans l'édition en ce qui concerne la complexité. –

+0

@ user470379: au lieu de 'clear' +' insert', vous pouvez utiliser 'assign'. –

+0

bonne explication sur les complexités .... m'a beaucoup aidé ... – Naveen

0

L'objet comparateur (pas seulement le type) devient membre de la carte. Lors de l'affectation, les éléments et le comparateur sont copiés. C'est pourquoi map2 acquiert le même ordre que map1. Pour copier les éléments, vous pouvez utiliser map2.insert(map1.begin(), map1.end()).

+1

Vous pouvez également considérer que cette carte supporte reverse_iterator. maintenez une carte simple (toujours croissante), mais utilisez (m.begin(), m.end()) quand vous voulez un ordre ascendant, et (m.rbegin(), m.rend()) quand vous voulez un ordre décroissant. Ce n'est pas tout à fait un choix d'exécution comme vous le souhaitez, mais cela peut aider –

+0

ya .... Mon but est différent ... Je ne sais pas jusqu'à l'exécution, que les données doivent être stockées de manière ascendante ou descendante. est même dans les deux cas ... j'ai toujours été marre en utilisant sinon si pour la même chose .. if (condition) forward_iter else reverse_iter ... les deux types d'iter ne sont pas non plus les mêmes pour la programmation générique ... – Naveen