简体   繁体   English

STL 中是否有已排序的容器?

[英]Is there a sorted container in the STL?

Is there a sorted container in the STL? STL 中是否有已排序的容器?

What I mean is following: I have an std::vector<Foo> , where Foo is a custom made class.我的意思是:我有一个std::vector<Foo> ,其中Foo是一个定制的类。 I also have a comparator of some sort which will compare the fields of the class Foo .我还有一个比较器,可以比较Foo类的字段。

Now, somewhere in my code I am doing:现在,在我的代码中我正在做的某处:

std::sort( myvec.begin(), myvec.end(), comparator );

which will sort the vector according to the rules I defined in the comparator.这将根据我在比较器中定义的规则对向量进行排序。

Now I want to insert an element of class Foo into that vector.现在我想将Foo类的元素插入到该向量中。 If I could, I would like to just write:如果可以,我只想写:

 mysortedvector.push_back( Foo() );

and what would happen is that the vector will put this new element according to the comparator to its place.并且会发生的是,向量将根据比较器将这个新元素放置到它的位置。

Instead, right now I have to write:相反,现在我必须写:

myvec.push_back( Foo() );
std::sort( myvec.begin(), myvec.end(), comparator );

which is just a waste of time, since the vector is already sorted and all I need is to place the new element appropriately.这只是浪费时间,因为向量已经排序,我需要的只是适当地放置新元素。

Now, because of the nature of my program, I can't use std::map<> as I don't have a key/value pairs, just a simple vector.现在,由于我的程序的性质,我不能使用std::map<>因为我没有键/值对,只有一个简单的向量。

If I use stl::list , I again need to call sort after every insertion.如果我使用stl::list ,我再次需要在每次插入后调用 sort 。

Yes, std::set , std::multiset , std::map , and std::multimap are all sorted using std::less as the default comparison operation.是的, std::setstd::multisetstd::mapstd::multimap都使用std::less作为默认比较操作进行排序。 The underlying data-structure used is typically a balanced binary search tree such as a red-black tree.使用的底层数据结构通常是平衡二叉搜索树,例如红黑树。 So if you add an element to these data-structures and then iterate over the contained elements, the output will be in sorted order.因此,如果您向这些数据结构添加一个元素,然后迭代包含的元素,输出将按排序顺序。 The complexity of adding N elements to the data-structure will be O(N log N), or the same as sorting a vector of N elements using any common O(log N) complexity sort.向数据结构添加 N 个元素的复杂度将是 O(N log N),或者与使用任何常见的 O(log N) 复杂度排序对 N 个元素的向量进行排序相同。

In your specific scenario, since you don't have key/value pairs, std::set or std::multiset is probably your best bet.在您的特定场景中,由于您没有键/值对,因此std::setstd::multiset可能是您最好的选择。

I'd like to expand on Jason's answer .我想扩展杰森的回答 I agree to Jason, that either std::set or std::multiset is the best choice for your specific scenario.我同意 Jason 的观点,即std::setstd::multiset是您特定场景的最佳选择。 I'd like to provide an example in order to help you to further narrow down the choice.我想提供一个示例,以帮助您进一步缩小选择范围。

Let's assume that you have the following class Foo :假设您有以下类Foo

class Foo {
public:
    Foo(int v1, int v2) : val1(v1), val2(v2) {};
    bool operator<(const Foo &foo) const { return val2 < foo.val2; }
    int val1;
    int val2;
};

Here, Foo overloads the < operator.在这里, Foo重载了<操作符。 This way, you don't need to specify an explicit comparator function.这样,您无需指定显式比较器函数。 As a result, you can simply use a std::multiset instead of a std::vector in the following way.因此,您可以通过以下方式简单地使用std::multiset而不是std::vector You just have to replace push_back() by insert() :你只需push_back() insert()替换push_back() insert()

int main()
{
    std::multiset<Foo> ms;
    ms.insert(Foo(1, 6));
    ms.insert(Foo(1, 5));
    ms.insert(Foo(3, 4));
    ms.insert(Foo(2, 4));

    for (auto const &foo : ms)
        std::cout << foo.val1 << " " << foo.val2 << std::endl;

    return 0;
}

Output:输出:

3 4 3 4
2 4 2 4
1 5 1 5
1 6 1 6

As you can see, the container is sorted by the member val2 of the class Foo , based on the < operator.如您所见,容器根据<运算符按Foo类的成员val2排序。 However, if you use std::set instead of a std::multiset , then you will get a different output:但是,如果您使用std::set而不是std::multiset ,那么您将获得不同的输出:

int main()
{
    std::set<Foo> s;
    s.insert(Foo(1, 6));
    s.insert(Foo(1, 5));
    s.insert(Foo(3, 4));
    s.insert(Foo(2, 4));

    for (auto const &foo : s)
        std::cout << foo.val1 << " " << foo.val2 << std::endl;

    return 0;
}

Output:输出:

3 4 3 4
1 5 1 5
1 6 1 6

Here, the second Foo object where val2 is 4 is missing, because a std::set only allows for unique entries.此处,缺少val2为 4 的第二个Foo对象,因为std::set仅允许唯一条目。 Whether entries are unique is decided based on the provided < operator.条目是否唯一取决于提供的<运算符。 In this example, the < operator compares the val2 members to each other.在此示例中, <运算符将val2成员相互比较。 Therefore, two Foo objects are equal, if their val2 members have the same value.因此,如果两个Foo对象的val2成员具有相同的值,则它们是相等的。

So, your choice depends on whether or not you want to store Foo objects that may be equal based on the < operator.因此,您的选择取决于您是否要存储基于<运算符可能相等的Foo对象。

Code on Ideone Ideone 上的代码

C++ do have sorted container eg std::set and std::map C++ 确实有排序的容器,例如 std::set 和 std::map

int main() 
{ 
    //ordered set
    set<int> s; 
    s.insert(5); 
    s.insert(1); 
    s.insert(6); 
    s.insert(3); 
    s.insert(7); 
    s.insert(2); 

    cout << "Elements of set in sorted order: "; 
    for (auto it : s) 
        cout << it << " "; 

    return 0; 
} 

Output: Elements of set in sorted order: 1 2 3 5 6 7输出:按排序顺序排列的集合元素:1 2 3 5 6 7

int main() 
{ 
    // Ordered map 
    std::map<int, int> order; 

    // Mapping values to keys 
    order[5] = 10; 
    order[3] = 5; 
    order[20] = 100; 
    order[1] = 1; 

   // Iterating the map and printing ordered values 
   for (auto i = order.begin(); i != order.end(); i++) { 
       std::cout << i->first << " : " << i->second << '\n'; 
} 

Output:输出:
1 : 1 1 : 1

3 : 5 3 : 5

5 : 10 5 : 10

20 : 100 20 : 100

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM