快速获取多个最小(最大)元素C++的数据结构
Data structure that quickly get multiple min(max) elements C++
我正在尝试将一些元素存储到一个容器中,并希望根据一些标准高效地获取它。
简单地说,假设:
- 记录如下:(ID、年龄、工资)
- 对于每次插入和删除,它都会返回最低年龄的工资总额
如以下
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;
地图的密钥是
Age
。地图的价值是给定年龄段所有工资的总和。
假设对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,则在重复加减过程中会累积舍入误差。如果这是一个问题,研究如何正确处理舍入错误将是你的家庭作业。
确实没有标准容器可以满足您的需求,但编写自己的适配器类应该不难。
该类可以包含实际数据的向量、指向具有当前最小年龄的结构的指针或引用的向量、作为堆栈的当前最小年龄本身,以及包含年龄->和映射的映射。
-
添加数据:
添加新结构时,您可以比较当前最小年龄(年龄堆栈的顶部),如果它大于当前最小年龄,则只需将其添加到数据向量中,并更新年龄->总和映射中的总和。
如果年龄等于当前最小年龄,则添加数据并更新年龄->总和图。
如果新添加的数据的年龄小于当前最小值,则将其添加到数据向量中,将新年龄推送到堆栈中,并将新条目添加到年龄->总和映射中。
-
删除数据:
对于所有数据,将其从向量中移除,并更新年龄->总和图。
如果年龄等于当前最小年龄,并且年龄->总和映射中的总和已达到零,则弹出年龄堆栈。新的总和是年龄->总和图中新年龄的总和。
通过使用一张不断更新的地图和一堆最小年龄,你不必重新计算总数,因为它们总是最新的。
- 求最大元素位置的分治算法
- 使用堆查找第K个最大元素的时间复杂性
- 查找矩阵C++中每一列和每一行的最小和最大元素
- 2 个数组中最大元素的乘积
- 在最小堆中查找最大元素
- 用于查找数组中最大元素的出现次数的代码,给出分段错误
- 使用 std::min_element、std::max_element 查找矢量中的最小和最大元素
- C++ 函数,用于查找数组中四个最小最大元素的总和不起作用
- 是否有一个 std::set 函数来确定不超过数字 x 的最大元素?
- 找到对称矩阵的最大元素的最有效算法是什么
- 查找列'k'右侧的最大元素
- 如何找到双向链表的最大元素?
- 在 C++ 中,仅使用递归来提取向量中的最大元素
- 从给定范围内的向量中查找最大元素
- 如何找到具有用户定义谓词的向量的最大元素
- 如何找到 n 个最大元素的索引
- 如何将向量一的所有元素与向量二进行比较,如果存在最大元素,则将向量二的所有元素与向量三进行比较?
- 用于快速排序的最大元素交换次数
- 在 2D 向量中从每一行添加最大元素,以使行元素 $A_i$ 小于 $A_(i+1)$
- C 最小/最大元素