#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
‘soperator>=
, который не является компаратором строгого слабого порядка и, следовательно, незаконным.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 , так что все в порядке.