Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
99 pmbaty 1
/*
2
    Texel - A UCI chess engine.
3
    Copyright (C) 2013  Peter Ă–sterlund, peterosterlund2@gmail.com
4
 
5
    This program is free software: you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 3 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
 
19
/*
20
 * heap.hpp
21
 *
22
 *  Created on: Oct 3, 2013
23
 *      Author: petero
24
 */
25
 
26
#ifndef HEAP_HPP_
27
#define HEAP_HPP_
28
 
29
#include <vector>
30
#include <memory>
31
#include <type_traits>
32
#include <iostream>
33
 
34
template <typename T> class Heap;
35
 
36
/** A Heap that holds pointers to elements of type T.
37
 * T must inherit from HeapObject.
38
 * Destructing a T removes it from its heap.
39
 */
40
template <typename T>
41
class Heap {
42
public:
43
    /** Base class for objects that can be inserted in a heap. */
44
    class HeapObject {
45
    public:
46
        HeapObject();
47
        ~HeapObject();
48
        HeapObject(const HeapObject&) = delete;
49
        HeapObject& operator=(const HeapObject&) = delete;
50
 
51
        /** Get priority of element in heap. */
52
        int getPrio() const;
53
 
54
        /** Changes the priority. Does nothing if element not in a heap. */
55
        void newPrio(int prio);
56
    private:
57
        friend class Heap;
58
 
59
        Heap<T>* owner;
60
        int prio;
61
        int heapIdx;
62
    };
63
 
64
    /** Constructor. Creates an empty heap. */
65
    Heap();
66
 
67
    /** Destructor. Removes all elements from heap. */
68
    ~Heap();
69
 
70
    Heap(const Heap& other) = delete;
71
    Heap& operator=(const Heap& other) = delete;
72
 
73
    /** Insert an element in the heap. */
74
    void insert(const std::shared_ptr<T>& e, int prio);
75
 
76
    /** Remove an element from the heap. Does nothing if e not in heap. */
77
    void remove(const std::shared_ptr<T>& e);
78
    void remove(T* e);
79
 
80
    /** Change the priority of an element in the heap. */
81
    void newPrio(const std::shared_ptr<T>& e, int prio);
82
    void newPrio(T* e, int prio);
83
 
84
    /** Get the element with the highest priority. The element is not removed.
85
     * Returns null if heap is empty. */
86
    std::shared_ptr<T> front() const;
87
 
88
    /** Return true if heap is empty. */
89
    bool empty() const;
90
 
91
    /** Return number of elements in the heap. */
92
    int size() const;
93
 
94
    /** For debugging. */
95
    void print(std::ostream& os) const;
96
 
97
private:
98
    /** Swap two elements in the heap vector and update heapIdx. */
99
    void swapElems(int idx1, int idx2);
100
 
101
    /** Calls upHeap() or downHeap() as needed to restore heap condition. */
102
    void fixHeap(int idx);
103
 
104
    /** Moves an element up until the heap condition is satisfied.*/
105
    void upHeap(int idx);
106
 
107
    /** Moves an element down until the heap condition is satisfied. */
108
    void downHeap(int idx);
109
 
110
    /** Vector of heap elements. */
111
    std::vector<std::shared_ptr<T>> heap;
112
};
113
 
114
template <typename T> inline Heap<T>::Heap() {
115
    static_assert(std::is_base_of<HeapObject,T>::value, "T must inherit HeapObject");
116
}
117
 
118
template <typename T> inline Heap<T>::~Heap() {
119
    for (int i = (int)heap.size() - 1; i >= 0; i--)
120
        remove(heap[i]);
121
}
122
 
123
template <typename T> inline void Heap<T>::insert(const std::shared_ptr<T>& e, int prio) {
124
    assert(!e->owner);
125
    e->owner = this;
126
    e->prio = prio;
127
    int idx = (int)heap.size();
128
    e->heapIdx = idx;
129
    heap.push_back(e);
130
    upHeap(idx);
131
}
132
 
133
template <typename T> inline void Heap<T>::remove(const std::shared_ptr<T>& e) {
134
    remove(e.get());
135
}
136
 
137
template <typename T> inline void Heap<T>::remove(T* e) {
138
    if (!e->owner)
139
        return;
140
    int idx = e->heapIdx;
141
    int last = (int)heap.size() - 1;
142
    if (idx < last)
143
        swapElems(e->heapIdx, last);
144
    e->owner = nullptr;
145
    e->heapIdx = -1;
146
    heap.pop_back();
147
    if (idx < last)
148
        fixHeap(idx);
149
}
150
 
151
template <typename T> inline void Heap<T>::newPrio(const std::shared_ptr<T>& e, int prio) {
152
    newPrio(e.get(), prio);
153
}
154
 
155
template <typename T> inline void Heap<T>::newPrio(T* e, int prio) {
156
    e->prio = prio;
157
    fixHeap(e->heapIdx);
158
}
159
 
160
template <typename T> inline std::shared_ptr<T> Heap<T>::front() const {
161
    if (heap.empty())
162
        return nullptr;
163
    return heap[0];
164
}
165
 
166
template <typename T> bool Heap<T>::empty() const {
167
    return heap.empty();
168
}
169
 
170
template <typename T> int Heap<T>::size() const {
171
    return (int)heap.size();
172
}
173
 
174
template <typename T> inline void Heap<T>::swapElems(int idx1, int idx2) {
175
    std::swap(heap[idx1]->heapIdx, heap[idx2]->heapIdx);
176
    heap[idx1].swap(heap[idx2]);
177
}
178
 
179
template <typename T> inline void Heap<T>::fixHeap(int idx) {
180
    int parent = (idx - 1) / 2;
181
    if ((idx > 0) && (heap[parent]->prio < heap[idx]->prio)) {
182
        swapElems(idx, parent);
183
        upHeap(parent);
184
    } else {
185
        downHeap(idx);
186
    }
187
}
188
 
189
template <typename T> inline void Heap<T>::upHeap(int idx) {
190
    while (idx > 0) {
191
        int parent = (idx - 1) / 2;
192
        if (heap[parent]->prio >= heap[idx]->prio)
193
            break;
194
        swapElems(idx, parent);
195
        idx = parent;
196
    }
197
}
198
 
199
template <typename T> inline void Heap<T>::downHeap(int idx) {
200
    int hSize = (int)heap.size();
201
    while (true) {
202
        int child = idx * 2 + 1;
203
        if (child >= hSize)
204
            break;
205
        if ((child + 1 < hSize) && (heap[child]->prio < heap[child+1]->prio))
206
            child++;
207
        if (heap[idx]->prio >= heap[child]->prio)
208
            break;
209
        swapElems(idx, child);
210
        idx = child;
211
    }
212
}
213
 
214
template <typename T> inline Heap<T>::HeapObject::HeapObject()
215
    : owner(nullptr), prio(0), heapIdx(-1) {
216
}
217
 
218
template <typename T> inline Heap<T>::HeapObject::~HeapObject() {
219
    if (owner)
220
        owner->remove(static_cast<T*>(this));
221
}
222
 
223
template <typename T> inline int Heap<T>::HeapObject::getPrio() const {
224
    return prio;
225
}
226
 
227
template <typename T> inline void Heap<T>::HeapObject::newPrio(int prio) {
228
    if (owner)
229
        owner->newPrio(static_cast<T*>(this), prio);
230
}
231
 
232
template <typename T> inline void Heap<T>::print(std::ostream& os) const {
233
    int hSize = heap.size();
234
    for (int i = 0; i < hSize; i++)
235
        os << std::setw(2) << i << ' ';
236
    os << '\n';
237
    for (int i = 0; i < hSize; i++)
238
        os << std::setw(2) << heap[i]->prio << ' ';
239
    os << '\n';
240
}
241
 
242
#endif /* HEAP_HPP_ */