开发者

STL std::map dynamic ordering

I know this may be a silly question. but stil i have a confusion. W.r.t std::map. i have written a custom predicate for dymanic ordering of map,

enum OrderingType 
{
    ASCENDING, 
    DESCENDING 
};

template <class T>
class Ordering
{
    OrderingType m_o开发者_如何学Crder;

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 is

  1. We can decide the ordering of data elements in the map on some conditions

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

  2. We can use same forward iterator for both ascending & descending ordered map

    in the below code. map's ordering works fine in both ascending & descending order ( amp1 & map2 ). But on assignment map2 = map1, the ordering of map2 changes along with the content. I was expected to copy only content, not the change in the ordering. further inserts on map2 ( which was declared as descending) will be in ascending order.

Any suggestions or idea..? or defining two way ordering predicate for map is bad idea..?

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


Well setting map2 = map1 is going to in fact copy the whole object, not just the elements. What you probably want to do then is

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

I believe off the top of my head that the complexity of the two steps together is going to be O(n log n), but don't quote me on that.

Edit

Even better (O(n)):

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

"For the third version ( insert (first,last) ), Nlog(size+N) in general (where N is the distance between first and last, and size the size of the container before the insertion), but linear if the elements between first and last are already sorted according to the same ordering criterion used by the container." (http://cplusplus.com/reference/stl/map/insert)


The comparator object (not just the type) becomes a member of the map. On assignment, both the elements and the comparator are copied. That is why map2 acquires the same ordering as map1.

To just copy the elements, you can use map2.insert(map1.begin(), map1.end()).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜