Min stl приоритетная очередь для хранения верхних m элементов из всего массива показывает неправильный вывод. В этом примере отсортированный вектор будет [1,3,3,3,3,5,5,5,5,8,8,8,8,8]. Таким образом, верхний "m", где m = 5, должен быть 1,3,3,3,3, но на выходе будет 1,3,3,3,5. Может ли кто-нибудь предложить, почему он не работает в случае повторяющихся записей. Вот пример кода.
#include <iostream>
#include <queue>
using namespace std;
struct compare
{
bool operator()(const int& l, const int& r)
{
return l > r;
}
};
int main()
{
priority_queue<int,vector<int>, compare > pq;
vector <int> p;
p.push_back(3);
p.push_back(3);
p.push_back(3);
p.push_back(3);
p.push_back(5);
p.push_back(5);
p.push_back(5);
p.push_back(5);
p.push_back(1);
p.push_back(8);
p.push_back(8);
p.push_back(8);
p.push_back(8);
p.push_back(8);
for(int i=0;i<p.size();i++)
{
int k= p[i];
if(pq.size() < 5) // top 'm' elements say m = 5 here
{
pq.push(k);
}
else if (pq.top() >= k)
{
pq.pop();
pq.push(k);
}
}
while ( !pq.empty() )
{
cout << pq.top() << endl;
pq.pop();
}
cin.get();
}
Неправильный вывод:
1
3
3
3
5
Но правильный вывод должен быть
1
3
3
3
3
4 ответа
Определенная вами очередь приоритетов фактически перемещает значения от наименьшего к наивысшего от top
до самого низа до момента в коде, когда очередь приоритета size <= 5
, но после этого он заменяет самое низкое в настоящее время значение в PQ (равняется вершине PQ) на новое самое низкое значение, которое нужно вставить. Следовательно, вы теряете второе наименьшее значение в итоговом PQ.
Вместо того, чтобы заменять самое низкое значение вторым самым низким, вы должны вытолкнуть самое высокое (самое нижнее в PQ), что невозможно IMO без использования реализации двойной очереди (или стека), а также не рекомендуется для более высокой временной сложности .
Решение:
Измените определение pq
с
priority_queue<int,vector<int>, compare > pq;
К
priority_queue<int,vector<int>> pq;
Получите обратную сторону PQ, чтобы получить ответ :
Сделайте list::push_front(pq.top)
и вставляйте элементы в PQ, пока PQ не станет пустым, а затем распечатайте список, используя
for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it <<endl;
Найдите рабочий код здесь
Когда if(pq.size() < 5)
в вашей итерации по p
вы заполняете pq
3 3 3 3 5
После этого условие else if (pq.top() >= k)
выполняет работу, и вы заменяете значение top
3
наименьшим значением в p
. Это 1
. Итак, наконец, у вас есть:
1 3 3 3 5
Если ваша цель - найти и сохранить 5 верхних элементов вектора, рассмотрите возможность использования std::partial_sort_copy
вместо priority_queue
:
std::array<int, 5> arr;
std::partial_sort_copy(p.begin(), p.end(), arr.begin(), arr.end());
Таким образом вы сохраните свои первые 5 элементов в arr
.
Примечание: вы можете использовать список инициализаторов, чтобы настроить вектор в одну строку
vector <int> p{3,3,3,3,5,5,5,5,1,8,8,8,8,8};
Вы можете сделать следующее
int main()
{
std::priority_queue<int, std::vector<int>, std::less<>> pq;
for(int i : {3, 3, 3, 3, 5, 5, 5, 5, 1, 8, 8, 8, 8, 8}) {
if (pq.size() < 5 || i < pq.top()) {
pq.push(i);
}
if (pq.size() > 5)
{
pq.pop();
}
}
while (!pq.empty()) {
std::cout << pq.top() << std::endl;
pq.pop();
}
}
С обратным дисплеем.
Похожие вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.