2010-12-16 3 views
3

Я знаю, что это может быть глупый вопрос. но у меня есть путаница. W.r.t std :: map. я написал собственный предикат для dymanic упорядочения карты,STL std :: map динамический заказ

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; 
    } 
}; 

Преимущество

  1. Мы можем решить упорядочение элементов данных в карте на некоторых условиях

    типа OrderType = (условие? ПОДРАЗДЕЛЕНИЕ: ПОЛОЖЕНИЕ); CUSTOMMAP m (тип);

  2. Мы можем использовать тот же вперед итератор и для восходящей & нисходящого упорядоченной карты

    в коде ниже. Заказ карты отлично работает как по возрастанию & по убыванию (amp1 & map2). Но при присваивании map2 = map1 упорядочивание map2 изменяется вместе с содержимым. Я должен был скопировать только контент, а не изменение заказа. дальнейшие вставки на map2 (который был объявлен как нисходящий) будут в порядке возрастания.

Любые предложения или идеи ..? или определение двухстороннего предиката для карты - плохая идея ..?

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; 
} 

ответ

5

Ну установка map2 = map1 собирается фактически скопировать весь объект, а не только элементы. То, что вы, вероятно, хотите сделать тогда

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

Я считаю, что с верхней части моей головы, что сложность этих двух этапов вместе собирается быть O(n log n), но не цитируйте меня на этом.

Редактировать

Еще лучше (O(n)):

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

«Для третьей версии (вставка (первая, последняя)), Nlog (размер + N) в целом (где N является расстояние между первым и последним и размер размера контейнера перед вставкой), но линейно, если элементы между первым и последним уже отсортированы в соответствии с одним и тем же критерием упорядочения, используемым контейнером ». (http://cplusplus.com/reference/stl/map/insert)

+0

Хорошая точка в редактировании относительно сложности. – 2010-12-16 05:45:05

+0

@ user470379: вместо `clear` +` insert` вы можете использовать `assign`. – 2010-12-16 07:41:45

0

Объект компаратора (а не только тип) становится членом карты. При назначении копируются как элементы, так и компаратор. Вот почему map2 получает тот же порядок, что и map1.

Чтобы скопировать элементы, вы можете использовать map2.insert(map1.begin(), map1.end()).