我已經在一個優先級隊列使用二進制堆工作,並已開發了這個類,如下圖所示。模板類處理價值和參考語義
#include <iostream>
#include <type_traits>
template<class T, int N>
class BinaryHeap{
template<class T1>
class has_less_than_operator
{
private:
class no{};
template<class X>
static auto has(X&& t) -> decltype (t.operator < (t));
static no has(...);
public:
enum {
value = !std::is_same<
decltype(has(std::declval<T1>())),
no>::value
};
};
static_assert(std::is_copy_assignable<T>::value &&
std::is_copy_constructible<T>::value,
"Must be copy assignable and constructable");
public:
BinaryHeap() : used_(0){
}
BinaryHeap(BinaryHeap const& other) = default;
BinaryHeap& operator = (BinaryHeap const& other) = default;
inline T& max(){
return elements_[FIRST];
}
inline T const & max() const{
return elements_[FIRST];
}
void insert(T const& item){
elements_[++used_] = item;
swim(used_);
}
inline bool full() const{
return used_ == N;
}
void deleteMax(){
std::swap(elements_[used_],elements_[FIRST]);
sink(FIRST);
elements_[used_--] = T();
}
private:
template<class T1>
class has_dereference_operator
{
private:
class no{};
template<class X>
static auto has(X&& t) -> decltype (t.operator *());
static no has(...);
public:
enum {
value = !std::is_same<
decltype(has(std::declval<T1>())),
no>::value
};
};
inline bool parent_less(int position,std::integral_constant<int,0> i){
return elements_[ position/2] < elements_[position];
}
inline bool parent_less(int position,std::integral_constant<int,1> i){
return *(elements_[ position/2]) < *(elements_[position]);
}
void swim(int position){
while(position > 1 && parent_less(position,std::integral_constant<int, has_dereference_operator<T>::value>()))
{
std::swap(elements_[ position/2], elements_[position]);
position /= 2;
}
}
inline int which_less(int p1, int p2, std::integral_constant<int,0> i){
return (elements_[ p1] < elements_[p2]) ? p1 : p2;
}
inline int which_less(int p1, int p2, std::integral_constant<int,1> i){
return (*(elements_[ p1]) < *(elements_[p2])) ? p1 : p2;
}
inline int which_greater(int p1, int p2, std::integral_constant<int,0> i){
return (elements_[ p1] < elements_[p2]) ? p2 : p1;
}
inline int which_greater(int p1, int p2, std::integral_constant<int,1> i){
return (*(elements_[ p1]) < *(elements_[p2])) ? p2 : p1;
}
void sink(int position){
while(position * 2 <= used_){
int first = position * 2;
if(first > used_) break;
int greater_child = which_greater(first, first + 1, std::integral_constant<int, has_dereference_operator<T>::value>());
int lesser = which_less(greater_child, position, std::integral_constant<int, has_dereference_operator<T>::value>());
if(lesser == greater_child)
break;
std::swap(elements_[greater_child], elements_[position]);
position = greater_child;
}
}
inline int current_position() const{
return used_ + 1;
}
static const int MAX = N + 1;
static const int FIRST = 1;
static const int LAST = N;
T elements_[MAX];
int used_;
};
int main(int argc, const char * argv[])
{
BinaryHeap<int, 10> b;
b.insert(1);
b.insert(20);
b.insert(21);
b.insert(3);
b.insert(2);
std::cout << "Max: " << b.max() << std::endl;
b.deleteMax();
std::cout << "Max: " << b.max() << std::endl;
return 0;
}
雖然我有這個工作,我需要處理的差異比較說一個指針/共享指針說使用解引用運算符和值只是使用它們。我目前正在使用SFINAE來做這個的基礎上,如果類有運營商*。
這是實現這一目標的正確方法嗎?
布萊爾
我爲什麼要實現優先級隊列,當有'的std :: priority_queue'和奈堆時,有'的std :: make_heap'等除此之外,我不知道你爲什麼基於提供什麼類型的改變行爲?您可以使用包裝或謂詞。 – dyp
那實際上不是重點。這是一個學習練習。我知道std :: priority_queue。 –
交換的慣用方式是使用std :: swap; swap(foo,bar);'。這將調用特定於類型的'swap(T&,T&)'(如果存在),並且如果不存在則返回到'std :: swap'。 – Casey