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
-2
ganapathi 7 Сен 2016 в 08:58

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;

Найдите рабочий код здесь

0
Saurav Sahu 7 Сен 2016 в 07:49

Когда 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 
0
Nikita 7 Сен 2016 в 06:10

Если ваша цель - найти и сохранить 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};

Пример рабочего кода

0
Ap31 7 Сен 2016 в 07:56

Вы можете сделать следующее

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();  
    }  
}

С обратным дисплеем.

0
Jarod42 7 Сен 2016 в 09:15