【问题标题】:What would best data structure to support priority, updating , push and pop支持优先级、更新、推送和弹出的最佳数据结构是什么
【发布时间】:2025-12-21 09:00:11
【问题描述】:

编写应用程序: 我需要在哪里维护一个数据结构“X-Files”,它存储许多对象并支持以下功能:

  1. Pop - 移除具有最小值的对象(名为“Area51”的对象属性之一)
  2. Push - 将对象插入数据结构中
  3. 检查 - 给定对象是否在数据结构“X-Files”中
  4. 更新 - 更新对象的内容(涉及更新属性“Area51”并保证更新将严格低于当前值)

最适合支持这些要求的数据结构是什么?

【问题讨论】:

  • 我认为 Stack 数据结构可以达到目的。
  • @A2H:如何检查堆栈中的所有现有值?

标签: c++ algorithm c++11 data-structures


【解决方案1】:

std::set 应该可以完成这项工作。

虽然您的问题可能类似于使用 std::priority_queue,但不要落入陷阱,因为原版 priority_queue 不支持更新现有元素(除了头部),也不支持有效地检查其中是否存在元素.

【讨论】:

  • 我正在查看 std::set 的文档。对我来说,问题是,关键与优先级的属性不同。接下来是 std::set 不允许重复键。我可能会错过如何使用。我希望你能详细说明一下。
  • @skn2 我不确定我是否在关注。只需确保 std::set Compare(第二个模板参数)正在检查元素的优先级。如果您想允许多个具有相同优先级的元素,请确保它根据您对象的其他属性进行平局。
  • 但是,std::set 也不支持修改密钥。更新必须以移除-更新-插入序列的形式发生。
  • @Angew,如果你也使用emplace_hint(),它很容易实现,而且效率很高。
【解决方案2】:

如果优先级和键是不同的属性,您可以使用 2-index multi_index_container。快速而肮脏的例子如下:

Live Coliru Demo

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>

using namespace boost::multi_index;

struct element
{
 int key;
 int area51;
};

using x_files_base=multi_index_container<
  element,
  indexed_by<
    ordered_non_unique<member<element,int,&element::area51>>,
    hashed_unique<member<element,int,&element::key>>
  >
>;

class x_files:x_files_base
{
public:
  using x_files_base::iterator;
  using x_files_base::const_iterator;

  using x_files_base::x_files_base;
  using x_files_base::begin;
  using x_files_base::end;

  void pop(){erase(begin());}
  bool push(const element& x){return insert(x).second;}
  bool check(int key){return project<0>(get<1>().find(key))!=end();}

  void update(int key,int area51)
  {
    auto it=project<0>(get<1>().find(key));
    if(it!=end())modify(it,[=](element& x){x.area51=area51;});
  }
};

#include <iostream>
#include <string>

void dump(const x_files& xf)
{
  std::string delim="";
  for(const element& x:xf){
    std::cout<<delim<<"["<<x.key<<","<<x.area51<<"]";
    delim=",";
  }
  std::cout<<"\n";
}

int main()
{
  x_files xf={{100,0},{80,1},{90,2},{95,3}};

  dump(xf);
  xf.pop();
  dump(xf);
  xf.push({70,4});
  dump(xf);
  std::cout<<(xf.check(70)?"true":"false")<<"\n";
  xf.update(70,0);
  dump(xf);
}

输出

[100,0],[80,1],[90,2],[95,3] [80,1],[90,2],[95,3] [80,1],[90,2],[95,3],[70,4] 真的 [70,0],[80,1],[90,2],[95,3]

【讨论】:

  • OP 没有提到提升。
  • 也没说他用不了
  • @JoaquínMLópezMuñoz:太棒了。赞赏。我没有安装 boost,但现在这迫使我安装它。