快速获取多个最小(最大)元素C++的数据结构

Data structure that quickly get multiple min(max) elements C++

本文关键字:最大 元素 C++ 数据结构 获取      更新时间:2023-10-16

我正在尝试将一些元素存储到一个容器中,并希望根据一些标准高效地获取它。

简单地说,假设:

  1. 记录如下:(ID、年龄、工资)
  2. 对于每次插入和删除,它都会返回最低年龄的工资总额

如以下

       ID  Age Wage(k)
insert 1   23  95   // returns 23,95
insert 2   21  75   // returns 21,75
insert 3   27  85   // returns 21,75
insert 4   21  65   // returns 21,140
delete ID=2         // returns 21,65

我能想到几个解决方案:

1.矢量(boost::circular _buffer?)

e.g. [(23,1,95), (21,2,75), (27,3,85), (21,4,65)]
Insert: O(1)
Delete (can use a bit to mark deleted) O(n)
GetMinSum: O(n)

2.排序向量

e.g. [(21,2,75), (21,4,65), (23,1,95), (27,3,85)]
Insert: O(n)
Delete (can use a bit to mark deleted) O(n)
GetMinSum: O(1)

3.地图(RB树)

std::map<age, vector<record>>
[(21)->[(2,75),(1,65)], (23)->[(1,95)], (27)->[(3,85)]]
GetMinSum: O(1)
Insert: O(logN)
Delete: O(n)

有什么建议吗?

应该可以使用std::map:在O(1)中实现步骤2的计算部分

std::map<int, int> sum_of_wages_by_age;
  1. 地图的密钥是Age

  2. 地图的价值是给定年龄段所有工资的总和。

假设对std::map的键进行迭代必须以严格的弱顺序进行迭代,则最低的Age将始终是映射中的第一个键。因此,最低年龄的工资总额将简单地为:

auto p=sum_of_wages_by_age.begin();
return p == sum_of_wages_by_age.end() ? 0: // Edge case, empty map
          p->second;

我的答案只关心跟踪这张地图的内容,以便以这种方式快速返回最低年龄的工资总额。这与您需要如何存储<Id, Wage, Age>记录本身是完全不同的。这是一个单独的问题。这取决于你是否想把它们存储在向量中,或者其他什么东西中。无论您如何存储它们,sum_of_wages_by_age的唯一目的就是能够快速返回正确的数字。眼前的主题只涉及能够以这种方式有效地退还最低年龄的工资总额。

为了使这种方法发挥作用,每当插入和删除记录时,都需要不断更新上面的映射。这可以按如下方式进行。

添加新的<ID, Age, Wage>记录

除了存储此记录外,还需要将工资添加到地图中:

sum_of_wages_by_age[age] += wage;

删除现有<ID, Age, Wage>记录

这个更令人兴奋一点。

auto p=sum_of_wages_by_age.find(age);
if ( (p->second -= wage) == 0)
    sum_of_wages_by_age.erase(p);

你想保持整洁。删除给定年龄的最后一条记录后,您希望现在从该地图中完全删除该年龄的条目。如果你不在乎,你可以简单地做

sum_of_wages_by_age[age] -= wage;

请注意,因为被删除的记录必须是以前添加的,所以您可以保证地图上会有年龄的条目。当然,只有当wage不能为零或为负时,这才有效。但这是一个安全的假设。正如你所知,有一项法律规定了最低工资必须是多少

洞穴

以上示例使用int表示工资。如果需要使用float s或double s,则在重复加减过程中会累积舍入误差。如果这是一个问题,研究如何正确处理舍入错误将是你的家庭作业。

确实没有标准容器可以满足您的需求,但编写自己的适配器类应该不难。

该类可以包含实际数据的向量、指向具有当前最小年龄的结构的指针或引用的向量、作为堆栈的当前最小年龄本身,以及包含年龄->和映射的映射。

  • 添加数据:

    添加新结构时,您可以比较当前最小年龄(年龄堆栈的顶部),如果它大于当前最小年龄,则只需将其添加到数据向量中,并更新年龄->总和映射中的总和。

    如果年龄等于当前最小年龄,则添加数据并更新年龄->总和图。

    如果新添加的数据的年龄小于当前最小值,则将其添加到数据向量中,将新年龄推送到堆栈中,并将新条目添加到年龄->总和映射中。

  • 删除数据:

    对于所有数据,将其从向量中移除,并更新年龄->总和图。

    如果年龄等于当前最小年龄,并且年龄->总和映射中的总和已达到零,则弹出年龄堆栈。新的总和是年龄->总和图中新年龄的总和。

通过使用一张不断更新的地图和一堆最小年龄,你不必重新计算总数,因为它们总是最新的。