простой способ поддерживать минимальную кучу с помощью stl?

#c #stl #heap #min-heap

#c #stl #куча #минимальная куча

Вопрос:

для определяемой пользователем структуры, как я понимаю, это просто. Просто перегрузите operator < . Однако для int / float и т. Д. Мне действительно нужно перегружать operator < для int? Вот что я попробовал:

        #include <iostream>
       #include <algorithm>
       #include <vector>
       using namespace std;

       bool comp(const intamp; a, const intamp; b)
       {
          return a<b?false:true;
       }

       int main () 
       {
         int myints[] = {10,20,30,5,15};
         vector<int> v(myints,myints 5);
         vector<int>::iterator it;
         make_heap(v.begin(), v.end(), comp);
         cout << "initial min heap   : " << v.front() << endl;
         for (unsigned i=0; i<v.size(); i  ) cout << " " << v[i];
         cout<<endl;

         pop_heap (v.begin(),v.end());
         v.pop_back();
         for (unsigned i=0; i<v.size(); i  ) cout << " " << v[i];
         cout<<endl;
       }
  

результаты:

         initial min heap   : 5
        5 10 30 20 15
        30 10 15 20
  

теперь pop_heap, push_heap не будут корректно поддерживать минимальную кучу? есть ли более простой способ добиться этого?
Спасибо!

Редактировать: извините, я не внимательно проверил руководство. да, передача comp в pop_heap или push_heap должна помочь. Однако, что вы имеете в виду, я не должен использовать внешний компаратор? Если это неправильный способ, каков общий способ добиться этого?

Ответ №1:

Использовать std::greater<int>() в качестве компаратора (для всех make_heap , push_heap , pop_heap ). Важны () std::greater<int> это класс функтора, а не функция, поэтому вам нужен его экземпляр.

Ответ №2:

Ответы хороши, поэтому я просто хотел добавить небольшой пример. Допустим, у вас есть следующий массив:

 array<int, 10> A{5,2,8,3,4,1,9,12,0,7};
  

и вы хотите создать min heap . Самый быстрый способ сделать это — использовать make_heap алгоритм. Однако это создает max heap по умолчанию. Другими словами, если вы вызываете:

 make_heap(A.begin(), A.end());
  

A становится max heap . min heap С другой стороны, чтобы иметь a, вам нужно добавить компаратор, но не нужно его реализовывать. Вместо этого вызовите метод следующим образом:

 make_heap(A.begin(), A.end(), greater<int>());
  

Этот вызов сделает ваш массив a min heap .

PS: #include <algorithm> необходимо использовать std::make_heap . Те же операции применяются и к vector .

HTH!

Ответ №3:

Вам не нужно перегружать operator < for int (на самом деле вы не можете). Если вы используете внешний компаратор, вы также должны передавать то Comparator comp же самое pop_head .

* Редактировать: *

Как указал ильджарн, ваш оператор сравнения не реализует отношение строгого слабого порядка.

 a < b ? false : true; --> a >= b
b < a ? true : false; --> a > b
  

Комментарии:

1. Большая проблема заключается в том, что его компаратор эквивалентен int ‘s operator>= , который не является компаратором строгого слабого порядка и, следовательно, незаконным.

2. извините, я не внимательно изучил руководство. да, передача comp в pop_heap или push_heap должна помочь. Однако, что вы имеете в виду, я не должен использовать внешний компаратор? Если это неправильный способ, каков общий способ добиться этого?

3. @user268451: вы можете использовать внешний компаратор, если хотите, но он должен реализовывать отношение строгого слабого порядка, поэтому логический эквивалент operator>= не допускается, но логический эквивалент operator< или operator> есть. См. Эту превосходную статью для получения дополнительной информации, автором которой является один из самых отцов современного C : Порядок, я говорю!

4. @user268451: вы должны просто полностью избавиться от своего пользовательского компаратора и использовать std::greater<int>() вместо него.

5. @user268451: предположим a == b . Тогда a<b?false:true верно. Это неправильно, в соответствии с 25.3 / 4 C 03 требуется, чтобы компаратор обладал свойством, которое !comp(x,x) для всех x . Однако b<a?true:false значение равно false , так что все в порядке.