- /* 
-     Texel - A UCI chess engine. 
-     Copyright (C) 2013  Peter Ă–sterlund, peterosterlund2@gmail.com 
-   
-     This program is free software: you can redistribute it and/or modify 
-     it under the terms of the GNU General Public License as published by 
-     the Free Software Foundation, either version 3 of the License, or 
-     (at your option) any later version. 
-   
-     This program is distributed in the hope that it will be useful, 
-     but WITHOUT ANY WARRANTY; without even the implied warranty of 
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
-     GNU General Public License for more details. 
-   
-     You should have received a copy of the GNU General Public License 
-     along with this program.  If not, see <http://www.gnu.org/licenses/>. 
- */ 
-   
- /* 
-  * heap.hpp 
-  * 
-  *  Created on: Oct 3, 2013 
-  *      Author: petero 
-  */ 
-   
- #ifndef HEAP_HPP_ 
- #define HEAP_HPP_ 
-   
- #include <vector> 
- #include <memory> 
- #include <type_traits> 
- #include <iostream> 
-   
- template <typename T> class Heap; 
-   
- /** A Heap that holds pointers to elements of type T. 
-  * T must inherit from HeapObject. 
-  * Destructing a T removes it from its heap. 
-  */ 
- template <typename T> 
- class Heap { 
- public: 
-     /** Base class for objects that can be inserted in a heap. */ 
-     class HeapObject { 
-     public: 
-         HeapObject(); 
-         ~HeapObject(); 
-         HeapObject(const HeapObject&) = delete; 
-         HeapObject& operator=(const HeapObject&) = delete; 
-   
-         /** Get priority of element in heap. */ 
-         int getPrio() const; 
-   
-         /** Changes the priority. Does nothing if element not in a heap. */ 
-         void newPrio(int prio); 
-     private: 
-         friend class Heap; 
-   
-         Heap<T>* owner; 
-         int prio; 
-         int heapIdx; 
-     }; 
-   
-     /** Constructor. Creates an empty heap. */ 
-     Heap(); 
-   
-     /** Destructor. Removes all elements from heap. */ 
-     ~Heap(); 
-   
-     Heap(const Heap& other) = delete; 
-     Heap& operator=(const Heap& other) = delete; 
-   
-     /** Insert an element in the heap. */ 
-     void insert(const std::shared_ptr<T>& e, int prio); 
-   
-     /** Remove an element from the heap. Does nothing if e not in heap. */ 
-     void remove(const std::shared_ptr<T>& e); 
-     void remove(T* e); 
-   
-     /** Change the priority of an element in the heap. */ 
-     void newPrio(const std::shared_ptr<T>& e, int prio); 
-     void newPrio(T* e, int prio); 
-   
-     /** Get the element with the highest priority. The element is not removed. 
-      * Returns null if heap is empty. */ 
-     std::shared_ptr<T> front() const; 
-   
-     /** Return true if heap is empty. */ 
-     bool empty() const; 
-   
-     /** Return number of elements in the heap. */ 
-     int size() const; 
-   
-     /** For debugging. */ 
-     void print(std::ostream& os) const; 
-   
- private: 
-     /** Swap two elements in the heap vector and update heapIdx. */ 
-     void swapElems(int idx1, int idx2); 
-   
-     /** Calls upHeap() or downHeap() as needed to restore heap condition. */ 
-     void fixHeap(int idx); 
-   
-     /** Moves an element up until the heap condition is satisfied.*/ 
-     void upHeap(int idx); 
-   
-     /** Moves an element down until the heap condition is satisfied. */ 
-     void downHeap(int idx); 
-   
-     /** Vector of heap elements. */ 
-     std::vector<std::shared_ptr<T>> heap; 
- }; 
-   
- template <typename T> inline Heap<T>::Heap() { 
-     static_assert(std::is_base_of<HeapObject,T>::value, "T must inherit HeapObject"); 
- } 
-   
- template <typename T> inline Heap<T>::~Heap() { 
-     for (int i = (int)heap.size() - 1; i >= 0; i--) 
-         remove(heap[i]); 
- } 
-   
- template <typename T> inline void Heap<T>::insert(const std::shared_ptr<T>& e, int prio) { 
-     assert(!e->owner); 
-     e->owner = this; 
-     e->prio = prio; 
-     int idx = (int)heap.size(); 
-     e->heapIdx = idx; 
-     heap.push_back(e); 
-     upHeap(idx); 
- } 
-   
- template <typename T> inline void Heap<T>::remove(const std::shared_ptr<T>& e) { 
-     remove(e.get()); 
- } 
-   
- template <typename T> inline void Heap<T>::remove(T* e) { 
-     if (!e->owner) 
-         return; 
-     int idx = e->heapIdx; 
-     int last = (int)heap.size() - 1; 
-     if (idx < last) 
-         swapElems(e->heapIdx, last); 
-     e->owner = nullptr; 
-     e->heapIdx = -1; 
-     heap.pop_back(); 
-     if (idx < last) 
-         fixHeap(idx); 
- } 
-   
- template <typename T> inline void Heap<T>::newPrio(const std::shared_ptr<T>& e, int prio) { 
-     newPrio(e.get(), prio); 
- } 
-   
- template <typename T> inline void Heap<T>::newPrio(T* e, int prio) { 
-     e->prio = prio; 
-     fixHeap(e->heapIdx); 
- } 
-   
- template <typename T> inline std::shared_ptr<T> Heap<T>::front() const { 
-     if (heap.empty()) 
-         return nullptr; 
-     return heap[0]; 
- } 
-   
- template <typename T> bool Heap<T>::empty() const { 
-     return heap.empty(); 
- } 
-   
- template <typename T> int Heap<T>::size() const { 
-     return (int)heap.size(); 
- } 
-   
- template <typename T> inline void Heap<T>::swapElems(int idx1, int idx2) { 
-     std::swap(heap[idx1]->heapIdx, heap[idx2]->heapIdx); 
-     heap[idx1].swap(heap[idx2]); 
- } 
-   
- template <typename T> inline void Heap<T>::fixHeap(int idx) { 
-     int parent = (idx - 1) / 2; 
-     if ((idx > 0) && (heap[parent]->prio < heap[idx]->prio)) { 
-         swapElems(idx, parent); 
-         upHeap(parent); 
-     } else { 
-         downHeap(idx); 
-     } 
- } 
-   
- template <typename T> inline void Heap<T>::upHeap(int idx) { 
-     while (idx > 0) { 
-         int parent = (idx - 1) / 2; 
-         if (heap[parent]->prio >= heap[idx]->prio) 
-             break; 
-         swapElems(idx, parent); 
-         idx = parent; 
-     } 
- } 
-   
- template <typename T> inline void Heap<T>::downHeap(int idx) { 
-     int hSize = (int)heap.size(); 
-     while (true) { 
-         int child = idx * 2 + 1; 
-         if (child >= hSize) 
-             break; 
-         if ((child + 1 < hSize) && (heap[child]->prio < heap[child+1]->prio)) 
-             child++; 
-         if (heap[idx]->prio >= heap[child]->prio) 
-             break; 
-         swapElems(idx, child); 
-         idx = child; 
-     } 
- } 
-   
- template <typename T> inline Heap<T>::HeapObject::HeapObject() 
-     : owner(nullptr), prio(0), heapIdx(-1) { 
- } 
-   
- template <typename T> inline Heap<T>::HeapObject::~HeapObject() { 
-     if (owner) 
-         owner->remove(static_cast<T*>(this)); 
- } 
-   
- template <typename T> inline int Heap<T>::HeapObject::getPrio() const { 
-     return prio; 
- } 
-   
- template <typename T> inline void Heap<T>::HeapObject::newPrio(int prio) { 
-     if (owner) 
-         owner->newPrio(static_cast<T*>(this), prio); 
- } 
-   
- template <typename T> inline void Heap<T>::print(std::ostream& os) const { 
-     int hSize = heap.size(); 
-     for (int i = 0; i < hSize; i++) 
-         os << std::setw(2) << i << ' '; 
-     os << '\n'; 
-     for (int i = 0; i < hSize; i++) 
-         os << std::setw(2) << heap[i]->prio << ' '; 
-     os << '\n'; 
- } 
-   
- #endif /* HEAP_HPP_ */ 
-