Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将自定义数据推入优先级队列时出现无效堆错误_C++_Heap_Priority Queue - Fatal编程技术网

C++ 将自定义数据推入优先级队列时出现无效堆错误

C++ 将自定义数据推入优先级队列时出现无效堆错误,c++,heap,priority-queue,C++,Heap,Priority Queue,我现在正试图解决一个问题,这个问题要求我在2维矩阵中找到最上面的k频繁数 我定义了一个结构numCount,它有两个字段:number来存储数字,count来存储其出现的时间。然后我访问矩阵中的每个数字,如果它的numCount结构已经存在于max堆中(按count排序),我只需将其count增加1;否则,我将创建一个新的numCount对象并将其推入堆中。注意,为了有效地获得与一个数字对应的numCount对象,我为它们的对应关系保留了一个unordered_map 我的想法的主要逻辑显示在下

我现在正试图解决一个问题,这个问题要求我在
2
维矩阵中找到最上面的
k
频繁数

我定义了一个结构
numCount
,它有两个字段:
number
来存储数字,
count
来存储其出现的时间。然后我访问矩阵中的每个数字,如果它的
numCount
结构已经存在于max堆中(按
count
排序),我只需将其
count
增加
1
;否则,我将创建一个新的
numCount
对象并将其推入堆中。注意,为了有效地获得与一个数字对应的
numCount
对象,我为它们的对应关系保留了一个
unordered_map

我的想法的主要逻辑显示在下面的代码中。但是,将一些
numCount
对象添加到堆中后,
push
操作会产生
无效堆
错误

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][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;
}
结构比较{ 布尔运算符(){ 返回左秒<右秒; } }; 向量kPopular(向量和nums,int k){ int m=nums.size(),n=nums[0].size(); 无序地图计数; for(int i=0;ik) st.erase(st.begin()); } 流行向量(k); set::迭代器itr=st.begin(); for(int i=0;i修改优先级队列中现有条目的密钥既是问题的原因,也是正确完成任务的一大障碍。出于您的目的,根本不需要这样做。
以增量方式保持优先级队列没有达到您已经确定的目的,并且会使算法效率低下,并且会造成上述难以纠正的问题

相反,您应该首先读取所有数据并计算所有计数。从数字到计数的映射对于该阶段来说要简单得多,并且比额外级别的间接寻址更有效

计算完所有计数后,就可以找到最大的k。优先级队列是查找k最大值的好工具的一种可能性,但有效地使用该队列需要颠倒k的意义。构建一个最多可容纳k个项目的队列,并始终标识这些k个项目中最小的(而不是最大的)。插入第一个k
数字,在Q中计数
对,然后对其余的每一对,将其与Q中最小的对进行比较,如果新的对大于旧的最小对,则用新的对替换Q中最小的对


如果你有一个很好的理由在计算计数时保持一个增量Q,那么这个理由在你的帖子中并不明显,你应该把它说清楚。使用支持更改现有项目密钥的优先级队列并非不可能。我在自己的工作中的许多地方都需要它,并选择编写自己的优先级队列(而不是使用std)以使这方面更容易。编写自己的代码并不难,但可能还有一种方法可以使用std版本。但在讨论这种复杂性之前,请解释为什么问题需要它。

修改优先级队列中现有条目的密钥既是问题的原因,也是正确完成任务的一大障碍。出于您的目的,根本不需要这样做。
以增量方式保持优先级队列没有达到您已经确定的目的,并且会使算法效率低下,并且会造成上述难以纠正的问题

相反,您应该首先读取所有数据并计算所有计数。从数字到计数的映射对于该阶段来说要简单得多,并且比额外级别的间接寻址更有效

计算完所有计数后,就可以找到最大的k。优先级队列是查找k最大值的好工具的一种可能性,但有效地使用该队列需要颠倒k的意义。构建一个最多可容纳k个项目的队列,并始终标识这些k个项目中最小的(而不是最大的)。插入第一个k
数字,在Q中计数
对,然后对其余的每一对,将其与Q中最小的对进行比较,如果新的对大于旧的最小对,则用新的对替换Q中最小的对


如果你有一个很好的理由在计算计数时保持一个增量Q,那么这个理由在你的帖子中并不明显,你应该把它说清楚。使用支持更改现有项目密钥的优先级队列并非不可能。我在自己的工作中的许多地方都需要它,并选择编写自己的优先级队列(而不是使用std)以使这方面更容易。编写自己的代码并不难,但可能还有一种方法可以使用std版本。但是在深入讨论这种复杂性之前,请解释为什么问题需要它。

我对C++没有什么了解,但是<代码> pq>代码>可能不喜欢你在修改元素之后,通过修改元素>比较(通过修改<代码>计数>代码>。我现在想尝试一下
set
。这段代码将被简化为按值存储对象,而不是使用指针,@MattMcNabb嗯,我使用指针是因为我需要保证无序映射
mp
中的
numCount
对象
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;
}