2 * Copyright 2013 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Paweł Dziepak, pdziepak@quarnos.org
8 #ifndef KERNEL_UTIL_HEAP_H
9 #define KERNEL_UTIL_HEAP_H
14 #include <SupportDefs.h>
17 template<typename Element
, typename Key
>
25 template<typename Element
, typename Key
>
28 typedef HeapLink
<Element
, Key
> Link
;
31 inline Link
* GetHeapLink();
37 template<typename Element
, typename Key
>
38 class HeapStandardGetLink
{
40 typedef HeapLink
<Element
, Key
> Link
;
43 inline Link
* operator()(Element
* element
) const;
46 template<typename Element
, typename Key
,
47 HeapLink
<Element
, Key
> Element::*LinkMember
>
48 class HeapMemberGetLink
{
50 typedef HeapLink
<Element
, Key
> Link
;
53 inline Link
* operator()(Element
* element
) const;
56 template<typename Key
>
57 class HeapLesserCompare
{
59 inline bool operator()(Key a
, Key b
);
62 template<typename Key
>
63 class HeapGreaterCompare
{
65 inline bool operator()(Key a
, Key b
);
68 #define HEAP_TEMPLATE_LIST \
69 template<typename Element, typename Key, typename Compare, typename GetLink>
70 #define HEAP_CLASS_NAME Heap<Element, Key, Compare, GetLink>
72 template<typename Element
, typename Key
,
73 typename Compare
= HeapLesserCompare
<Key
>,
74 typename GetLink
= HeapStandardGetLink
<Element
, Key
> >
78 Heap(int initialSize
);
81 inline Element
* PeekRoot() const;
83 static const Key
& GetKey(Element
* element
);
85 inline void ModifyKey(Element
* element
, Key newKey
);
87 inline void RemoveRoot();
88 inline status_t
Insert(Element
* element
, Key key
);
91 status_t
_GrowHeap(int minimalSize
= 0);
93 void _MoveUp(HeapLink
<Element
, Key
>* link
);
94 void _MoveDown(HeapLink
<Element
, Key
>* link
);
100 static Compare sCompare
;
101 static GetLink sGetLink
;
106 template<typename Element
, typename Key
>
107 HeapLink
<Element
, Key
>::HeapLink()
113 template<typename Element
, typename Key
>
114 HeapLink
<Element
, Key
>::HeapLink()
120 template<typename Element
, typename Key
>
121 HeapLink
<Element
, Key
>*
122 HeapLinkImpl
<Element
, Key
>::GetHeapLink()
128 template<typename Element
, typename Key
>
129 HeapLink
<Element
, Key
>*
130 HeapStandardGetLink
<Element
, Key
>::operator()(Element
* element
) const
132 return element
->GetHeapLink();
136 template<typename Element
, typename Key
,
137 HeapLink
<Element
, Key
> Element::*LinkMember
>
138 HeapLink
<Element
, Key
>*
139 HeapMemberGetLink
<Element
, Key
, LinkMember
>::operator()(Element
* element
) const
141 return &(element
->*LinkMember
);
145 template<typename Key
>
147 HeapLesserCompare
<Key
>::operator()(Key a
, Key b
)
153 template<typename Key
>
155 HeapGreaterCompare
<Key
>::operator()(Key a
, Key b
)
162 HEAP_CLASS_NAME::Heap()
172 HEAP_CLASS_NAME::Heap(int initialSize
)
178 _GrowHeap(initialSize
);
183 HEAP_CLASS_NAME::~Heap()
191 HEAP_CLASS_NAME::PeekRoot() const
193 if (fLastElement
> 0)
201 HEAP_CLASS_NAME::GetKey(Element
* element
)
203 return sGetLink(element
)->fKey
;
209 HEAP_CLASS_NAME::ModifyKey(Element
* element
, Key newKey
)
211 HeapLink
<Element
, Key
>* link
= sGetLink(element
);
213 ASSERT(link
->fIndex
>= 0 && link
->fIndex
< fLastElement
);
214 Key oldKey
= link
->fKey
;
217 if (sCompare(newKey
, oldKey
))
219 else if (sCompare(oldKey
, newKey
))
226 HEAP_CLASS_NAME::RemoveRoot()
228 ASSERT(fLastElement
> 0);
231 Element
* element
= PeekRoot();
232 HeapLink
<Element
, Key
>* link
= sGetLink(element
);
233 ASSERT(link
->fIndex
!= -1);
238 if (fLastElement
> 0) {
239 Element
* lastElement
= fElements
[fLastElement
];
240 fElements
[0] = lastElement
;
241 sGetLink(lastElement
)->fIndex
= 0;
242 _MoveDown(sGetLink(lastElement
));
249 HEAP_CLASS_NAME::Insert(Element
* element
, Key key
)
251 if (fLastElement
== fSize
) {
252 status_t result
= _GrowHeap();
257 ASSERT(fLastElement
!= fSize
);
259 HeapLink
<Element
, Key
>* link
= sGetLink(element
);
261 ASSERT(link
->fIndex
== -1);
263 fElements
[fLastElement
] = element
;
264 link
->fIndex
= fLastElement
++;
274 HEAP_CLASS_NAME::_GrowHeap(int minimalSize
)
276 int newSize
= max_c(max_c(fSize
* 2, 4), minimalSize
);
278 size_t arraySize
= newSize
* sizeof(Element
*);
280 = reinterpret_cast<Element
**>(realloc(fElements
, arraySize
));
281 if (newBuffer
== NULL
)
284 fElements
= newBuffer
;
293 HEAP_CLASS_NAME::_MoveUp(HeapLink
<Element
, Key
>* link
)
296 int parent
= (link
->fIndex
- 1) / 2;
298 && sCompare(link
->fKey
, sGetLink(fElements
[parent
])->fKey
)) {
300 sGetLink(fElements
[parent
])->fIndex
= link
->fIndex
;
302 Element
* element
= fElements
[link
->fIndex
];
303 fElements
[link
->fIndex
] = fElements
[parent
];
304 fElements
[parent
] = element
;
306 link
->fIndex
= parent
;
315 HEAP_CLASS_NAME::_MoveDown(HeapLink
<Element
, Key
>* link
)
320 current
= link
->fIndex
;
322 int child
= 2 * link
->fIndex
+ 1;
323 if (child
< fLastElement
324 && sCompare(sGetLink(fElements
[child
])->fKey
, link
->fKey
)) {
328 child
= 2 * link
->fIndex
+ 2;
329 if (child
< fLastElement
330 && sCompare(sGetLink(fElements
[child
])->fKey
,
331 sGetLink(fElements
[current
])->fKey
)) {
335 if (link
->fIndex
== current
)
338 sGetLink(fElements
[current
])->fIndex
= link
->fIndex
;
340 Element
* element
= fElements
[link
->fIndex
];
341 fElements
[link
->fIndex
] = fElements
[current
];
342 fElements
[current
] = element
;
344 link
->fIndex
= current
;
350 Compare
HEAP_CLASS_NAME::sCompare
;
353 GetLink
HEAP_CLASS_NAME::sGetLink
;
356 #endif // KERNEL_UTIL_HEAP_H