将自定义数据推入priority_queue时出现无效堆错误
invalid heap error when pushing self-defined data into the priority_queue
我现在正试图解决一个问题,该问题要求我找到2
维矩阵中的顶部k
频繁数。
我定义了一个结构numCount
,它有两个字段:number
用于存储数字,count
用于存储其出现时间。然后我访问矩阵中的每个数字,如果它的numCount
结构已经存在于一个最大堆中(按count
排序(,我只需将其count
增加1
;否则,我将创建一个新的numCount
对象并将其推送到堆中。注意,为了有效地获得与数字对应的numCount
对象,我为它们的对应关系保留了unordered_map
。
我的想法的主要逻辑显示在下面的代码中。但是,在向堆中添加一些numCount
对象后,push
操作会导致invalid heap
错误。
struct numCount {
int number;
int count;
numCount(int num) : number(num), count(1) {}
};
struct compare {
bool operator() (numCount*& lhs, numCount*& rhs) {
return lhs -> count > rhs -> count;
}
};
vector<int> kPopular(vector<vector<int> >& nums, int k) {
int m = nums.size(), n = nums[0].size();
priority_queue<numCount*, vector<numCount*>, compare> pq;
unordered_map<int, numCount*> mp;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (mp.find(nums[i][j]) != mp.end())
mp[nums[i][j]] -> count++;
else {
numCount* ncnt = new numCount(nums[i][j]);
pq.push(ncnt); // This line gives the "invalid heap" error.
mp[nums[i][j]] = ncnt;
}
}
}
vector<int> popular(k);
for (int i = 0; i < k; i++) {
popular[i] = pq.top() -> number;
pq.pop();
}
return popular;
}
我在以下矩阵上测试此代码:
nums = [[1, 1, 2],
[2, 2, 3]
[1, 2, 3]]
然后,当尝试在nums[1][2]
添加与第一个3
相对应的numCount
对象时,它抛出invalid heap
错误。
如何修复此错误?
更新:在接受@JSF的建议后,我更新了我的代码,如下所示。
struct compare {
bool operator() (const pair<int, int>& lhs, const pair<int, int>& rhs) const {
return lhs.second < rhs.second;
}
};
vector<int> kPopular(vector<vector<int> >& nums, int k) {
int m = nums.size(), n = nums[0].size();
unordered_map<int, int> counts;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
counts[nums[i][j]]++;
set<pair<int, int>, compare> st;
for (auto pr : counts) {
st.insert(pr);
if ((int)st.size() > k)
st.erase(st.begin());
}
vector<int> popular(k);
set<pair<int, int>, compare>::iterator itr = st.begin();
for (int i = 0; i < k; i++) {
popular[i] = (*itr).first;
itr = st.erase(itr);
}
return popular;
}
修改优先级队列中现有条目的键既是问题的原因,也是要正确完成的一大麻烦。就你的目的而言,根本没有必要这么做
递增地保持优先级队列并没有达到您已经确定的目的,并且会使您的算法效率低下,还会产生难以纠正的上述问题。
相反,您应该首先读取所有数据并计算所有计数。对于那个阶段,从数字到计数的映射要简单得多,而且比额外的间接级别更高效。
一旦你计算了所有的计数,你就可以找到最大的k。优先级队列是找到k个最大值的好工具的一种可能性,但该队列的有效使用将涉及颠倒k的意义。建立一个最多可容纳k个项目的队列,并始终识别k个项目中最小的(而不是最大的(。在Q中插入前k个number,count
对,然后对其余的每一个,将其与Q中最小的对进行比较,如果新的对大于旧的最小对,则用新的对替换Q中的最小对。
如果你有充分的理由在计算计数时保持增量Q,那么这个原因在你的帖子中并不明显,你应该明确这一点。使用支持更改现有项的键的优先级队列并非不可能。在我自己的工作中,我在很多地方都需要这一点,并选择编写自己的优先级队列(而不是使用std(,以使这一方面更容易。编写自己的代码并不难,但可能还有一种使用std版本的方法。但在讨论这种复杂性之前,请解释为什么问题需要它。
- 如何解决错误:SCIP C++中的 SCIP 阶段无效 <10>
- what(): basic_string::_M_construct 空无效错误
- C++ Linux 运行时basic_string::_M_construct null 无效错误
- 调用boost v1.58中的函数时出现模板名称使用无效错误
- 对象分配-成员函数的使用无效错误
- 从 WindowsAPI 调用 NetLocalGroupAddMembers 时,安全 ID 结构无效错误
- 为什么映射迭代器显示基本操作数无效错误
- 获取数组类型的无效错误
- 调用 vector.erase() 函数时指针操作无效错误
- C++:basic_string::_M_construct 空,对于图形 BFS 算法无效错误
- C++运行程序后给我 basic_string::_S_construct null 无效错误
- 使用 std::vector 时抽象类类型"Shape"的新表达式无效错误
- mmap 错误:分段错误/指针无效错误
- 从字符到字符编译器的转换无效错误
- 恒常性添加无效?错误:无法使用字符**初始化常量字符**
- 二进制表达式的操作数无效错误消息
- "从'文件* {aka _iobuf}'到'int'的转换无效"错误
- 在 boost 中序列化二进制数据失败,并出现"签名无效"错误
- 基类 T 无效错误
- 从“常量字符*”到“字符*”的转换无效错误