1a9643ea8Slogwang
2a9643ea8Slogwang /**
3a9643ea8Slogwang * Tencent is pleased to support the open source community by making MSEC available.
4a9643ea8Slogwang *
5a9643ea8Slogwang * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
6a9643ea8Slogwang *
7a9643ea8Slogwang * Licensed under the GNU General Public License, Version 2.0 (the "License");
8a9643ea8Slogwang * you may not use this file except in compliance with the License. You may
9a9643ea8Slogwang * obtain a copy of the License at
10a9643ea8Slogwang *
11a9643ea8Slogwang * https://opensource.org/licenses/GPL-2.0
12a9643ea8Slogwang *
13a9643ea8Slogwang * Unless required by applicable law or agreed to in writing, software distributed under the
14a9643ea8Slogwang * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15a9643ea8Slogwang * either express or implied. See the License for the specific language governing permissions
16a9643ea8Slogwang * and limitations under the License.
17a9643ea8Slogwang */
18a9643ea8Slogwang
19a9643ea8Slogwang
20a9643ea8Slogwang /**
21a9643ea8Slogwang * @filename heap.h
22*35a81399Slogwang * @info flexible insert and delete heap, if no random deletion, use std::make_heap
23a9643ea8Slogwang * @time 2013-06-11
24a9643ea8Slogwang */
25a9643ea8Slogwang
26a9643ea8Slogwang #ifndef __HEAP_ENTRY_FILE__
27a9643ea8Slogwang #define __HEAP_ENTRY_FILE__
28a9643ea8Slogwang
29a9643ea8Slogwang #include <stdlib.h>
30a9643ea8Slogwang #include <stdio.h>
31a9643ea8Slogwang #include <string.h>
32a9643ea8Slogwang #include <assert.h>
33a9643ea8Slogwang
34a9643ea8Slogwang #define heap_assert(statement)
35a9643ea8Slogwang //#define heap_assert(statement) assert(statement)
36a9643ea8Slogwang
37a9643ea8Slogwang namespace NS_MICRO_THREAD {
38a9643ea8Slogwang
39*35a81399Slogwang class HeapEntry;
40*35a81399Slogwang class HeapList;
41a9643ea8Slogwang
42a9643ea8Slogwang /**
43*35a81399Slogwang * @brief definition of heap elements for minimum heap
44a9643ea8Slogwang */
45a9643ea8Slogwang class HeapEntry
46a9643ea8Slogwang {
47a9643ea8Slogwang private:
48*35a81399Slogwang int _index;
49a9643ea8Slogwang
50a9643ea8Slogwang public:
51a9643ea8Slogwang friend class HeapList;
52a9643ea8Slogwang
HeapEntry()53a9643ea8Slogwang HeapEntry():_index(0){};
~HeapEntry()54a9643ea8Slogwang virtual ~HeapEntry(){};
55a9643ea8Slogwang
56a9643ea8Slogwang virtual unsigned long long HeapValue() = 0;
57a9643ea8Slogwang
HeapIterate()58a9643ea8Slogwang virtual void HeapIterate() {
59a9643ea8Slogwang return;
60a9643ea8Slogwang };
61a9643ea8Slogwang
62a9643ea8Slogwang inline int InsertIntoHeap(HeapList* list);
63a9643ea8Slogwang
64a9643ea8Slogwang inline int DeleteFromHeap(HeapList* list);
65a9643ea8Slogwang
GetIndex()66a9643ea8Slogwang inline int GetIndex() {
67a9643ea8Slogwang return _index;
68a9643ea8Slogwang };
69a9643ea8Slogwang
70a9643ea8Slogwang private:
71a9643ea8Slogwang
HeapValueCmp(HeapEntry * rhs)72a9643ea8Slogwang inline int HeapValueCmp(HeapEntry* rhs) {
73a9643ea8Slogwang if (this->HeapValue() == rhs->HeapValue()) {
74a9643ea8Slogwang return 0;
75a9643ea8Slogwang } else if (this->HeapValue() > rhs->HeapValue()) {
76a9643ea8Slogwang return 1;
77a9643ea8Slogwang } else {
78a9643ea8Slogwang return -1;
79a9643ea8Slogwang }
80a9643ea8Slogwang };
81a9643ea8Slogwang
SetIndex(int index)82a9643ea8Slogwang inline void SetIndex(int index) {
83a9643ea8Slogwang _index = index;
84a9643ea8Slogwang };
85a9643ea8Slogwang
86a9643ea8Slogwang
87a9643ea8Slogwang };
88a9643ea8Slogwang
89a9643ea8Slogwang
90a9643ea8Slogwang /**
91*35a81399Slogwang * @brief minimum heap queue.
92a9643ea8Slogwang */
93a9643ea8Slogwang class HeapList
94a9643ea8Slogwang {
95a9643ea8Slogwang private:
96*35a81399Slogwang HeapEntry** _list;
97*35a81399Slogwang int _max;
98*35a81399Slogwang int _count;
99a9643ea8Slogwang
100a9643ea8Slogwang public:
101a9643ea8Slogwang
102a9643ea8Slogwang explicit HeapList(int max = 100000) {
103a9643ea8Slogwang _max = (max > 0) ? max : 100000;
104a9643ea8Slogwang _list = (HeapEntry**)malloc (sizeof(HeapEntry*) * (_max+1));
105a9643ea8Slogwang heap_assert(_list);
106a9643ea8Slogwang memset(_list, 0, sizeof(HeapEntry*) * (_max+1));
107a9643ea8Slogwang _count = 0;
108a9643ea8Slogwang };
~HeapList()109a9643ea8Slogwang virtual ~HeapList() {
110a9643ea8Slogwang if (_list) {
111a9643ea8Slogwang free(_list);
112a9643ea8Slogwang _list = NULL;
113a9643ea8Slogwang }
114a9643ea8Slogwang _max = 0;
115a9643ea8Slogwang _count = 0;
116a9643ea8Slogwang };
117a9643ea8Slogwang
HeapResize(int size)118a9643ea8Slogwang int HeapResize(int size) {
119a9643ea8Slogwang if (_max >= size) {
120a9643ea8Slogwang return 0;
121a9643ea8Slogwang }
122a9643ea8Slogwang
123a9643ea8Slogwang HeapEntry** new_list = (HeapEntry**)malloc(sizeof(HeapEntry*) * (size+1));
124a9643ea8Slogwang if (NULL == new_list) {
125a9643ea8Slogwang return -1;
126a9643ea8Slogwang }
127a9643ea8Slogwang memset(new_list, 0, sizeof(HeapEntry*) * (size+1));
128a9643ea8Slogwang memcpy(new_list, _list, sizeof(HeapEntry*) * (_max+1));
129a9643ea8Slogwang free(_list);
130a9643ea8Slogwang _list = new_list;
131a9643ea8Slogwang _max = size;
132a9643ea8Slogwang
133a9643ea8Slogwang return 0;
134a9643ea8Slogwang };
135a9643ea8Slogwang
136a9643ea8Slogwang
137a9643ea8Slogwang int HeapPush(HeapEntry* entry);
138a9643ea8Slogwang
139a9643ea8Slogwang HeapEntry* HeapPop();
140a9643ea8Slogwang
141a9643ea8Slogwang int HeapDelete(HeapEntry* entry);
142a9643ea8Slogwang
143a9643ea8Slogwang void HeapForeach();
144a9643ea8Slogwang
HeapSize()145a9643ea8Slogwang int HeapSize() {
146a9643ea8Slogwang return _count;
147a9643ea8Slogwang };
148a9643ea8Slogwang
HeapTop()149a9643ea8Slogwang HeapEntry* HeapTop() {
150a9643ea8Slogwang return (_count > 0) ? _list[1] : NULL;
151a9643ea8Slogwang };
152a9643ea8Slogwang
153a9643ea8Slogwang private:
154a9643ea8Slogwang
HeapFull()155a9643ea8Slogwang bool HeapFull() {
156a9643ea8Slogwang return (_count >= _max);
157a9643ea8Slogwang };
158a9643ea8Slogwang
159*35a81399Slogwang
HeapEmpty()160a9643ea8Slogwang bool HeapEmpty() {
161a9643ea8Slogwang return (_count == 0);
162a9643ea8Slogwang };
163a9643ea8Slogwang
164a9643ea8Slogwang void HeapUp();
165a9643ea8Slogwang
166a9643ea8Slogwang void HeapDown(int index);
167a9643ea8Slogwang
168a9643ea8Slogwang };
169a9643ea8Slogwang
170*35a81399Slogwang
HeapUp()171a9643ea8Slogwang inline void HeapList::HeapUp()
172a9643ea8Slogwang {
173a9643ea8Slogwang for (int pos = _count; pos > 0; pos = pos/2)
174a9643ea8Slogwang {
175*35a81399Slogwang if (pos/2 < 1) // pos == 1 peaked, 0 reserved.
176a9643ea8Slogwang {
177a9643ea8Slogwang break;
178a9643ea8Slogwang }
179a9643ea8Slogwang
180a9643ea8Slogwang if (_list[pos]->HeapValueCmp(_list[pos/2]) < 0)
181a9643ea8Slogwang {
182a9643ea8Slogwang HeapEntry* tmp = _list[pos/2];
183a9643ea8Slogwang _list[pos/2] = _list[pos];
184a9643ea8Slogwang _list[pos] = tmp;
185a9643ea8Slogwang
186a9643ea8Slogwang _list[pos]->SetIndex(pos);
187a9643ea8Slogwang _list[pos/2]->SetIndex(pos/2);
188a9643ea8Slogwang }
189a9643ea8Slogwang else
190a9643ea8Slogwang {
191a9643ea8Slogwang break;
192a9643ea8Slogwang }
193a9643ea8Slogwang }
194a9643ea8Slogwang }
195a9643ea8Slogwang
196a9643ea8Slogwang
HeapDown(int index)197a9643ea8Slogwang inline void HeapList::HeapDown(int index)
198a9643ea8Slogwang {
199a9643ea8Slogwang int min_son;
200a9643ea8Slogwang for (int pos = index; pos <= _count; pos = min_son)
201a9643ea8Slogwang {
202*35a81399Slogwang if (pos*2 > _count) // pos is a leaf node.
203a9643ea8Slogwang {
204a9643ea8Slogwang break;
205a9643ea8Slogwang }
206a9643ea8Slogwang else if (pos*2 == _count)
207a9643ea8Slogwang {
208a9643ea8Slogwang min_son = pos*2;
209a9643ea8Slogwang }
210a9643ea8Slogwang else
211a9643ea8Slogwang {
212a9643ea8Slogwang if (_list[pos*2+1]->HeapValueCmp(_list[pos*2]) < 0)
213a9643ea8Slogwang {
214a9643ea8Slogwang min_son = pos*2+1;
215a9643ea8Slogwang }
216a9643ea8Slogwang else
217a9643ea8Slogwang {
218a9643ea8Slogwang min_son = pos*2;
219a9643ea8Slogwang }
220a9643ea8Slogwang }
221a9643ea8Slogwang
222a9643ea8Slogwang if (_list[pos]->HeapValueCmp(_list[min_son]) > 0)
223a9643ea8Slogwang {
224a9643ea8Slogwang HeapEntry* tmp = _list[min_son];
225a9643ea8Slogwang _list[min_son] = _list[pos];
226a9643ea8Slogwang _list[pos] = tmp;
227a9643ea8Slogwang
228a9643ea8Slogwang _list[pos]->SetIndex(pos);
229a9643ea8Slogwang _list[min_son]->SetIndex(min_son);
230a9643ea8Slogwang }
231a9643ea8Slogwang else
232a9643ea8Slogwang {
233a9643ea8Slogwang break;
234a9643ea8Slogwang }
235a9643ea8Slogwang }
236a9643ea8Slogwang }
237a9643ea8Slogwang
238a9643ea8Slogwang
HeapPush(HeapEntry * item)239a9643ea8Slogwang inline int HeapList::HeapPush(HeapEntry* item)
240a9643ea8Slogwang {
241a9643ea8Slogwang if (HeapFull()) {
242*35a81399Slogwang heap_assert(0); // it's possible in theory but not in fact.
243a9643ea8Slogwang return -1;
244a9643ea8Slogwang }
245a9643ea8Slogwang
246a9643ea8Slogwang if (item->GetIndex() != 0) {
247*35a81399Slogwang heap_assert(0); // duplicated insertion.
248a9643ea8Slogwang return -2;
249a9643ea8Slogwang }
250a9643ea8Slogwang
251a9643ea8Slogwang _count++;
252a9643ea8Slogwang _list[_count] = item;
253a9643ea8Slogwang item->SetIndex(_count);
254a9643ea8Slogwang
255a9643ea8Slogwang HeapUp();
256a9643ea8Slogwang
257a9643ea8Slogwang return 0;
258a9643ea8Slogwang }
259a9643ea8Slogwang
260a9643ea8Slogwang
HeapPop()261a9643ea8Slogwang inline HeapEntry* HeapList::HeapPop()
262a9643ea8Slogwang {
263a9643ea8Slogwang if (HeapEmpty()) {
264a9643ea8Slogwang return NULL;
265a9643ea8Slogwang }
266a9643ea8Slogwang
267*35a81399Slogwang HeapEntry* top = _list[1]; // 0 reserved.
268a9643ea8Slogwang
269a9643ea8Slogwang _list[1] = _list[_count];
270a9643ea8Slogwang _list[1]->SetIndex(1);
271a9643ea8Slogwang _list[_count] = 0;
272a9643ea8Slogwang
273a9643ea8Slogwang _count--;
274a9643ea8Slogwang HeapDown(1);
275a9643ea8Slogwang
276a9643ea8Slogwang heap_assert(top->GetIndex() == 1);
277a9643ea8Slogwang top->SetIndex(0);
278a9643ea8Slogwang return top;
279a9643ea8Slogwang }
280a9643ea8Slogwang
HeapDelete(HeapEntry * item)281a9643ea8Slogwang inline int HeapList::HeapDelete(HeapEntry* item)
282a9643ea8Slogwang {
283a9643ea8Slogwang if (HeapEmpty()) {
284a9643ea8Slogwang return -1;
285a9643ea8Slogwang }
286a9643ea8Slogwang
287a9643ea8Slogwang int pos = item->GetIndex() ;
288a9643ea8Slogwang if ((pos > _count) ||(pos <= 0))
289a9643ea8Slogwang {
290*35a81399Slogwang heap_assert(0); // duplicated deletion or illegal data.
291a9643ea8Slogwang return -2;
292a9643ea8Slogwang }
293a9643ea8Slogwang
294a9643ea8Slogwang HeapEntry* del = _list[pos];
295a9643ea8Slogwang _list[pos] = _list[_count];
296a9643ea8Slogwang _list[pos]->SetIndex(pos);
297a9643ea8Slogwang
298a9643ea8Slogwang _list[_count] = 0;
299a9643ea8Slogwang _count--;
300a9643ea8Slogwang
301a9643ea8Slogwang HeapDown(pos);
302a9643ea8Slogwang heap_assert(pos == del->GetIndex());
303a9643ea8Slogwang del->SetIndex(0);
304a9643ea8Slogwang return 0;
305a9643ea8Slogwang }
306a9643ea8Slogwang
307a9643ea8Slogwang
HeapForeach()308a9643ea8Slogwang inline void HeapList::HeapForeach()
309a9643ea8Slogwang {
310a9643ea8Slogwang int per = 1;
311a9643ea8Slogwang for (int i = 1; i <= _count; i++)
312a9643ea8Slogwang {
313a9643ea8Slogwang if (i >= per*2)
314a9643ea8Slogwang {
315a9643ea8Slogwang printf("\n");
316a9643ea8Slogwang per *=2;
317a9643ea8Slogwang }
318a9643ea8Slogwang printf("%llu ", _list[i]->HeapValue());
319a9643ea8Slogwang
320a9643ea8Slogwang _list[i]->HeapIterate();
321a9643ea8Slogwang }
322a9643ea8Slogwang }
323a9643ea8Slogwang
InsertIntoHeap(HeapList * list)324a9643ea8Slogwang inline int HeapEntry::InsertIntoHeap(HeapList* list) {
325a9643ea8Slogwang return list->HeapPush(this);
326a9643ea8Slogwang };
327a9643ea8Slogwang
DeleteFromHeap(HeapList * list)328a9643ea8Slogwang inline int HeapEntry::DeleteFromHeap(HeapList* list) {
329a9643ea8Slogwang return list->HeapDelete(this);
330a9643ea8Slogwang };
331a9643ea8Slogwang
332a9643ea8Slogwang } // namespace end
333a9643ea8Slogwang
334a9643ea8Slogwang #endif
335a9643ea8Slogwang
336a9643ea8Slogwang
337