【问题标题】:Sort objects with duplicate keys使用重复键对对象进行排序
【发布时间】:2012-04-10 22:30:05
【问题描述】:

我需要一长串按其中一个参数排序的对象。在 C++ 中最快的方法是什么?我需要能够在此列表中添加和删除元素,并且仍按该特定参数排序。

Class Foo {
private:
  int rank;
}

我希望我的所有Foo 对象按升序排列,添加或删除新对象时,它应该按顺序排列在正确的位置。也可以有多个对象具有相同的rank,因此键值对是不可能的。

知道如何在 C++ 中做到这一点吗?我正在查看make_heap(),但我不确定如何将它与对象一起使用(或者是否可以使用)。

【问题讨论】:

  • 或者更确切地说是 std::set - 除非您需要更改元素。
  • 虽然地图需要一个唯一键,但在我的场景中,可能有多个对象,其中我想要订购的对象的参数是相同的

标签: c++ list


【解决方案1】:

首先您应该为Foo 定义operator<(类似这样)...

inline bool operator< (const Foo& lhs, const Foo& rhs) {
  return lhs.rank < rhs.rank;
} 

需要声明为Foo的朋友:

class Foo {
 public:
  explicit Foo(int rank_init) : rank(rank_init) {}
  friend bool operator< (const Foo&, const Foo&);
 private:
  int rank;
};


现在您可以创建一个std::multiset&lt;Foo&gt;,它将保持Foos 按rank 升序排序,例如

std::multiset<Foo> foo_multiset;
foo_multiset.insert(Foo(5));  // 5
foo_multiset.insert(Foo(3));  // 3, 5
foo_multiset.insert(Foo(1));  // 1, 3, 5
foo_multiset.insert(Foo(3));  // 1, 3, 3, 5
size_t erased_count(foo_multiset.erase(Foo(3)));  // 1, 5 (erased_count == 2)

但不能保证在您的特定情况下这将是“最快”的选项。您需要为此进行概要分析。根据元素的数量、插入/擦除操作的频率和 STL 实现,您会发现排序后的std::vector&lt;Foo&gt; 更适合您的需求。

Scott Meyers 的 Effective STL 在第 23 项中描述了这种情况。

【讨论】:

  • 它是如何工作的,在将我的对象添加到多重集之前我是否调用操作员?如果两个等级相等会发生什么?感谢您的帮助!
  • multiset 使用std::less,它使用operator&lt; 来确定排序顺序。除了根据我的回答定义这些之外,您无需执行任何操作,您就可以开始了。 multiset 满足多个键相同的元素,因此您可以在容器中保留多个具有相同等级的Foos。
  • 还有一个问题:multiset 中的对象是否有序对性能有影响吗?我对模型进行了一些更改,不再需要订购它们,我只需要使用相同的密钥快速访问项目即可。
  • 在这种情况下,就性能而言,std::unordered_multiset&lt;Foo&gt; 可能会更好,或者如果您的编译器不支持,boost::unordered_multiset&lt;Foo&gt;。这些使用起来比std::multiset 稍微复杂一点;您必须定义 operator== 而不是 operator&lt; 并且还必须为 Foo 定义哈希函数。
  • 对此问题的最佳答案可能是查看unordered_multiset 的boost 文档,特别是描述Equality Predicates and Hash Functions 的部分。基本上,与 multiset 这样的关联容器相比,unordered_multiset 这样的哈希容器实现其查找机制的方式根本不同。
猜你喜欢
  • 2018-02-02
  • 1970-01-01
  • 2017-02-15
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
  • 1970-01-01
  • 1970-01-01
  • 2016-10-27
相关资源
最近更新 更多