堆排序以及优先队列


#include <iostream>

using std::swap;
template<typename T>
void heap_up(T & container, int cnt, int pos = 0){
    if(pos == 0)
        pos = cnt - 1;
    while(pos > 0 && container[pos] > container[(pos -1)/2]){
        swap(container[pos], container[(pos-1)/2]);
        pos = (pos - 1) / 2;
    }
}

template<typename T>
void heap_down(T & container, int cnt, int pos = 0){
    while(true){
        int left = pos * 2 + 1, right = pos * 2 + 2, index = pos;
        if(left < cnt && container[index] < container[left])
            index = left;
        if(right < cnt && container[index] < container[right])
            index = right;
        if(index == pos) break;
        swap(container[pos], container[index]);
        pos = index;
    }
}
template<typename T, typename V>
V heap_pop(T container, int cnt){
    swap(container[0], container[cnt -1]);
    heap_down(container, cnt -1);
    return container[cnt -1];
}
template<typename T, typename V>
int heap_push(T & container, int cnt, const V & value){
    container[cnt] = value;
    heap_up(container, cnt+1);
    return cnt + 1;
}
template<typename T>
void heap_build(T & container, int cnt){
    for(int root = (cnt - 2)/2; root >= 0; --root)
        heap_down(container, cnt, root);
}
template<typename T>
void heap_sort(T & container, int cnt){
    heap_build(container, cnt);
    //std::for_each(container.begin(), container.end(), [](const int & a){std::cout << a << " ";}); std::cout<<std::endl;
    for(int i = cnt - 1; i > 0; i--){
        std::swap(container[0], container[i]);
        heap_down(container, i, 0);
    }
}
#include <vector>
// #include <initializer_list>
template <typename T, typename Comp=std::less<T> >
class Heap{
    std::vector<T> datas;
    Comp comp;
    void build();
    void up(int pos);
    void down(int pos);
public:
    explicit Heap(const Comp & cmp=Comp()):comp(cmp){
        //std::cout<<"0 default construct" <<std::endl;
    }
    explicit Heap(const std::vector<T> & vec, const Comp & cmp=Comp()):datas(vec), comp(cmp){
        build();
        //std::cout<<"1 vector construct"<<std::endl;
    }
    explicit Heap(std::vector<T> && vec, const Comp & cmp=Comp()) noexcept :datas(vec), comp(cmp) {
        build();
        //std::cout<<"2 vector move construct"<<std::endl;
        // can be called as Heap<int> h({1,2,2}); without explicit
    }
    Heap(std::initializer_list<T> ilist, const Comp & cmp=Comp()):datas(ilist.begin(),ilist.end()), comp(cmp){
        build();
        //std::cout<<"3 list construct"<<std::endl;
        // can be called as Heap<int> a = {1,2,3}, b({2,3,4}), c{1,2,3,4};
    }
    template <typename Input>
    Heap(Input first, Input last, const Comp & cmp=Comp()):datas(first, last), comp(cmp){
        build();
        //std::cout<<"4 range construct" << std::endl;
    }
    Heap(Heap && h) noexcept :datas(std::move(h.datas)), comp(h.comp){ // 1
        //std::cout<<"5 move copy construct"<<std::endl;
        // can be called as Heap<int> h(std::move(hx)), h2 = std::move(hn);
    }
    Heap(const Heap & h):datas(h.datas), comp(h.comp){ // 2
        //std::cout<<"6 copy construct" << std::endl;
        // can be called as Heap<int> h(hx), h2 = hn;
    }
    Heap & operator = (const Heap & h){  // 3
        //std::cout<<"7 assignment copy" << std::endl;
        this->datas = h.datas;
        return *this;
        // be called as Heap<int> h1, h2; h1 = h2;
    }

    Heap & operator = (Heap && h) noexcept { // 4
        //std::cout<<"8 move assignment copy" << std::endl;
        this->datas = move(h.datas);
        return *this;
        // be called as Heap<int> h1, h2; h1 = std::move(h2); h2 = Heap<int>{};
    }
    ~Heap(){
        //std::cout<<"destruct Heap\n";
    }; // 5
    T top();
    void push(const T & v);
    void pop();
    bool empty();
    template <typename ... V> void emplace(V ... args){
        datas.emplace_back(args...);
        Heap<T, Comp>::up((int)datas.size() - 1);
    }
};

template <typename T, typename Comp>
void Heap<T, Comp>::up(int pos){
    while(pos > 0 && comp(datas[(pos-1)/2], datas[pos]))
    {
        std::swap(datas[pos], datas[(pos - 1)/2]);
        pos = (pos - 1) / 2;
    }
}

template <typename T, typename Comp>
void Heap<T, Comp>::down(int pos){
    while(true){
        int left = pos * 2 + 1, right = pos * 2 + 2, maxi = pos;
        if(left < datas.size() && comp(datas[maxi], datas[left]))
            maxi = left;
        if(right < datas.size() && comp(datas[maxi], datas[right]))
            maxi = right;
        if(maxi == pos) break;
        std::swap(datas[pos], datas[maxi]);
        pos = maxi;
    }
}

template <typename T, typename Comp>
T Heap<T, Comp>::top(){
    return datas[0];
}

template <typename T, typename Comp>
void Heap<T, Comp>::pop(){
    datas[0] = datas.back();
    datas.pop_back();
    Heap<T, Comp>::down(0);
}

template <typename T, typename Comp>
void Heap<T, Comp>::push(const T & v){
    datas.push_back(v);
    Heap<T, Comp>::up((int)datas.size() - 1);
}

template <typename T, typename Comp>
void Heap<T, Comp>::build(){
    for(int root = (int(datas.size()) - 2) / 2; root >= 0; root--)
        Heap<T, Comp>::down(root);
    //std::for_each(datas.begin(), datas.end(), [](const T & x){std::cout << x <<" ";}); std::cout << std::endl;
}

template <typename T, typename Comp>
bool Heap<T, Comp>::empty(){
    return datas.size() == 0;
}

Heap<int> htest(int x){
    Heap<int> h1;
    h1.emplace(x);
    return h1;
}

int test_heap(){
    std::vector<int> vec{3,4,5,6,7,89,1,2,3}, v2{3,4,5,6};
    Heap<int> h0, h7, h8;
    Heap<int> h1(vec);//, h11 = vec;
    //h0 = vec ;// 1 8
    Heap<int> h2(std::vector<int>{1,2,3}), h22(std::move(v2)); // 2
    Heap<int> h3={3,4,5}, h33({3,4,2,0}), h333{3,4,5,6}, h3333(Heap<int>{1,2,3});
    h3333 = Heap<int>();
    Heap<int> h4(vec.begin(), vec.end());
    //Heap<int> h5 = std::move(h2), h55(std::move(h1));下 
    Heap<int> h6 = h4, h66(h4);
    h7 = h4;
    h8 = std::move(h7);
    h8 = Heap<int>();
    std::cout<<"\ndone!\n";
    Heap<int> ht = htest(vec.size());
    Heap<int, std::greater<int>> h(vec);
    for(const auto &x:vec) h.emplace(x);
    while(!h.empty())
    {
        std::cout << h.top() << " ";
        h.pop();
    }
    return 0;
}
//int __heapmain = test_heap();

int mhsort(){
    std::vector<int> vec{9,3,4,5,6,7,0,2};
    heap_sort(vec, (int)vec.size());
    std::for_each(vec.begin(), vec.end(), [](const int & a){std::cout << a << " ";}); std::cout<<std::endl;
    return 0;
}
//int __mhsort = mhsort();

int main(){
    return 0;
}