【问题标题】:Which kind of STL should I use for this task? [closed]我应该使用哪种 STL 来完成这项任务? [关闭]
【发布时间】:2016-08-13 03:48:59
【问题描述】:

我需要一个必须添加/删除我拥有的一些结构的队列,例如:

struct MyObject
{
  int offset;
  BYTE status, data1, data2;
  double beatPos;

  enum Status
  {
    isOff = 8,
    isOn = 9,
  };
}   

当我.Add()一个元素时,这个队列必须把元素放在正确的位置,由于beatPos的值,它必须从较低的(队列顶部,即下一个元素我将pop)到上层(我将从中提取的最后一个元素)。

我看到有std::priority_queue,但我不确定是否可以选择哪个是订购字段。

另外,一旦我在列表中添加了一些结构,我想删除具有(例如)beatPos=1,567 的第一个元素(例如,它可能在列表的中间;不一定在开始)。

有什么线索吗?

【问题讨论】:

  • 多个MyObjects可以有相同的beatPos值吗?
  • @Zaiborg:当然可以!

标签: c++ list stack queue


【解决方案1】:

你想要的是std::multiset。它接受一个比较模板参数,默认为std::less 用于容器要存储的类型,但您可以指定不同的比较器。为此,我们可以创建一个 lambda,它将比较两个 MyObjects 并根据 beatPos 成员返回哪个对象应该具有更高的优先级

auto my_compare = [](const MyObject & lhs, const MyObject & rhs)
                    {
                        return lhs.beatPos < rhs.beatPos;
                    }

然后我们可以像这样使用它

std::multiset<MyObject, decltype(my_compare)> data(my_compare);

这将为您提供一个有序的容器,该容器可以存储多个具有相同 beatPos 的对象,并允许您访问容器的中间。

【讨论】:

  • 这不支持在容器中查找任意beatPos 值并删除它们,这是问题中的要求。
  • 问题第一部分的答案很好,但正如@JohnZwinck 所说,priority_queue 不适合按键访问..
  • @JohnZwinck 我错过了那部分要求。现在已经修复了。
【解决方案2】:

您可以将std::multiset 与用户定义的比较器一起使用。例如:

bool MyObjectComp(const MyObject& lhs, const MyObject& rhs) {
    return lhs.beatPos < rhs.beatPos;
}

typedef std::set<MyObject, MyObjectComp> MyObjectSet;

现在MyObjectSet 内的排序总是从最低到最高beatPos。可以使用lower_bound()upper_bound()进行搜索,使用begin()可以得到最小值。

请注意,由于double 值(IEEE 浮点)的性质,可能无法进行精确比较,因此您不一定要说mySet.find(0.5),但可以说mySet.upper_bound(0.49999)

同样的用户定义比较器也可用于priority_queue,但该容器不支持按值搜索元素,这是您的要求之一。

【讨论】:

  • 很好的答案,但这对于 OP 的要求是失败的,即可以有多个对象具有相同的 beatPos
  • @NathanOliver:很好,我将set 更改为multiset。其余的都是一样的。
  • 看起来我们俩都到了同一个地方;)
  • 不喜欢 std::multimap ;-)
  • @VolkerK:这里没有理由需要地图,因为键是值所固有的。这会浪费空间。
猜你喜欢
  • 2021-02-20
  • 2011-07-31
  • 2023-01-13
  • 2015-08-12
  • 1970-01-01
  • 1970-01-01
  • 2013-03-13
  • 1970-01-01
  • 2014-09-22
相关资源
最近更新 更多