-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheap.cpp
116 lines (99 loc) · 2.93 KB
/
heap.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "heap.h"
//heap declaration
heap::heap(int capacity) {
heap::capacity = capacity;
currSize = 0;
data.resize(capacity + 1);
mapping = new hashTable(capacity * 2);
}
//percolate up used for insertions and increase key operations
void heap::percolateUp(int posCur) {
if (posCur == 0) return;
node tmp = data[posCur];
int hole = posCur;
//traverse up (bubble up) the heap
for (; (hole > 1) && (tmp.key < data[hole / 2].key); hole /= 2) {
data[hole] = data[hole / 2];
mapping->setPointer(data[hole].id, &data[hole]);
}
//modify heap and hashtable
data[hole] = tmp;
mapping->setPointer(data[hole].id,&data[hole]);
}
//percolate down used for deletions and decrease key operations
void heap::percolateDown(int posCur) {
if (posCur == capacity || posCur == 0) return;
int child;
node tmp = data[posCur];
//traverse down the heap
for (; posCur * 2 <= currSize; posCur = child) {
if ((posCur * 2 == capacity) || (data[posCur * 2].key <= data[posCur * 2 + 1].key) && (tmp.key > data[posCur * 2].key)) {
data[posCur] = data[posCur * 2];
mapping->setPointer(data[posCur].id, &data[posCur]);
child = posCur * 2;
}
else if ((tmp.key > data[posCur*2+1].key)&&(data[posCur*2].key>data[posCur*2+1].key)){
data[posCur] = data[posCur * 2+1];
mapping->setPointer(data[posCur].id, &data[posCur]);
child = posCur * 2+1;
}
else break;
}
//modify heap and hashtable
data[posCur] = tmp;
mapping->setPointer(data[posCur].id, &data[posCur]);
}
//simple function that returns whether the heap is empty
bool heap::isEmpty() {
return currSize == 0?true:false;
}
//take a pointer from hashtable and return the position in heap
int heap::getPos(node *pn) {
int pos = pn - &data[0];
return pos;
}
int heap::insert(const std::string &id, int key, void *pv) {
if (currSize == data.size() - 1) return 1;
if (mapping->contains(id)) return 2;
node tmp;
tmp.id = id;
tmp.key = key;
tmp.pData = pv;
data[++currSize] = tmp;
mapping->insert(id, &data[currSize]);
percolateUp(currSize);
return 0;
}
int heap::setKey(const std::string &id, int key) {
bool b;
node *pn = static_cast<node *>(mapping->getPointer(id, &b));
if (!b) return 1;
int pos = getPos(pn);
pn->key = key;
percolateUp(pos);
percolateDown(pos);
return 0;
}
int heap::deleteMin(std::string *pId, int *pKey, void *ppData) {
if (isEmpty()) return 1;
if (pId) *pId = data[1].id;
if (pKey) *pKey = data[1].key;
if(ppData) *(static_cast<void **> (ppData)) = data[1].pData;
mapping->remove(data[1].id);
data[1] = data[currSize--];
percolateDown(1);
return 0;
}
int heap::remove(const std::string &id, int *pKey, void *ppData) {
bool b;
node *pn = static_cast<node *>(mapping->getPointer(id, &b));
int pos = getPos(pn);
if (b == false || pos == 0) return 1;
if (pKey) *pKey = data[pos].key;
if(ppData) *(static_cast<void **> (ppData)) = data[pos].pData;
mapping->remove(data[pos].id);
data[pos] = data[currSize--];
percolateDown(pos);
percolateUp(pos);
return 0;
}