【问题标题】:STL std::map dynamic orderingSTL std::map 动态排序
【发布时间】:2010-12-16 05:22:54
【问题描述】:

我知道这可能是一个愚蠢的问题。但我仍然感到困惑。 W.r.t 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 type = (条件 ? ASCENDING : DESCENDING ); 自定义地图 m(类型);

  2. 我们可以对升序和降序映射使用相同的前向迭代器

    在下面的代码中。地图的排序在升序和降序( amp1 和 map2 )中都可以正常工作。但是在赋值 map2 = map1 上,map2 的顺序会随着内容的变化而变化。我应该只复制内容,而不是顺序的变化。 map2 上的进一步插入(声明为降序)将按升序排列。

有什么建议或想法..?或者为 map 定义两种方式排序谓词是个坏主意..?

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

【问题讨论】:

    标签: c++


    【解决方案1】:

    设置map2 = map1 实际上会复制整个对象,而不仅仅是元素。那么你可能想要做的是

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

    我相信这两个步骤加在一起的复杂性将是O(n log n),但不要引用我的话。

    编辑

    更好 (O(n)):

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

    "对于第三个版本(insert (first,last)),一般是Nlog(size+N)(其中N是first和last之间的距离,size是插入前容器的大小),但是是线性的如果第一个和最后一个之间的元素已经根据容器使用的相同排序标准进行了排序。" (http://cplusplus.com/reference/stl/map/insert)

    【讨论】:

    • @user470379:你可以使用assign,而不是clear + insert
    • 所有stl容器的拷贝构造函数(和赋值运算符)都是O(n)。所以,我看不出使用这种方法的意义。如果您可以使用具有相同复杂性的更简单的语法,那就去做吧。
    • @Matthieu 可能很难使用map
    • @Alessandro "在下面的代码中。map 的排序在升序和降序( amp1 和 map2 )中都可以正常工作。但是在分配 map2 = map1 时,map2 的顺序会随着内容而变化。我预计仅复制内容,而不是更改顺序。在 map2 上的进一步插入(声明为降序)将按升序排列。"
    【解决方案2】:

    比较器对象(不仅仅是类型)成为映射的成员。在赋值时,元素和比较器都被复制。这就是为什么 map2 获得与 map1 相同的顺序。

    要仅复制元素,您可以使用map2.insert(map1.begin(), map1.end())

    【讨论】:

    • 您可能还想考虑 map 支持 reverse_iterator。 IE。你可以维护一个简单的地图(总是升序),但是当你想要升序时使用 (m.begin(), m.end()),当你想要降序时使用 (m.rbegin(), m.rend())命令。它并不完全是您想要的运行时选择,但它可能会有所帮助。
    • ya....我的目的不同...我不知道直到执行,数据是否必须以升序方式或降序方式存储。并且两种情况下的操作都是相同的......我总是厌倦了使用 if else 来做同样的事情.. if(condition) forward_iter else reverse_iter ...两种迭代器类型对于泛型编程也不相同...
    猜你喜欢
    • 2015-12-04
    • 1970-01-01
    • 2010-09-09
    • 2019-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-08
    相关资源
    最近更新 更多