mirror of https://gitee.com/bigwinds/arangodb
New version of PriorityQueue.
This commit is contained in:
parent
570509a58a
commit
4bdcfdb238
|
@ -45,11 +45,16 @@ namespace triagens {
|
|||
// store with the additional property that every Value has a
|
||||
// positive Weight (provided by the weight() and setWeight(w)
|
||||
// methods), which is a numerical type, and for which operator<
|
||||
// is defined. Furthermore, the Value type must be copyable and
|
||||
// movable. Finally, the Value type must have a method getKey that
|
||||
// returns a Key const&.
|
||||
// is defined. With respect to this weight the data structure
|
||||
// is at the same time a priority queue in that it is possible
|
||||
// to ask for (one of) the value(s) with the smallest weight and
|
||||
// remove this efficiently.
|
||||
// The Value type must be copyable and should be movable. Finally,
|
||||
// the Value type must have a method getKey that returns a Key
|
||||
// const&.
|
||||
// This data structure makes the following complexity promises
|
||||
// (amortized), where n is the number of key/value pairs stored:
|
||||
// (amortized), where n is the number of key/value pairs stored
|
||||
// in the queue:
|
||||
// insert: O(log(n)) (but see below)
|
||||
// lookup value by key: O(1)
|
||||
// get smallest: O(1)
|
||||
|
@ -60,6 +65,10 @@ namespace triagens {
|
|||
// and if we do not use lower weight by key, then we even get:
|
||||
// insert: O(1)
|
||||
// get and erase smallest: O(1)
|
||||
// With the "get and erase smallest" operation one has the option
|
||||
// of retaining the erased value in the key/value store. It can then
|
||||
// still be looked up but will no longer be considered for the
|
||||
// priority queue.
|
||||
|
||||
public:
|
||||
|
||||
|
@ -119,7 +128,8 @@ namespace triagens {
|
|||
}
|
||||
_heap.push_back(v);
|
||||
try {
|
||||
_lookup.insert(std::make_pair(k, _heap.size()-1 + _popped));
|
||||
_lookup.insert(std::make_pair(k,
|
||||
static_cast<ssize_t>(_heap.size()-1 + _popped)));
|
||||
}
|
||||
catch (...) {
|
||||
_heap.pop_back();
|
||||
|
@ -132,7 +142,8 @@ namespace triagens {
|
|||
_heap.push_back(v);
|
||||
try {
|
||||
size_t newpos = _heap.size() - 1;
|
||||
_lookup.insert(std::make_pair(k, newpos + _popped));
|
||||
_lookup.insert(std::make_pair(k,
|
||||
static_cast<ssize_t>(newpos + _popped)));
|
||||
repairUp(newpos);
|
||||
}
|
||||
catch (...) {
|
||||
|
@ -151,7 +162,14 @@ namespace triagens {
|
|||
if (it == _lookup.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return const_cast<Value const*>(&(_heap[it->second - _popped]));
|
||||
if (it->second >= 0) { // still in the queue
|
||||
return const_cast<Value const*>
|
||||
(&(_heap[static_cast<size_t>(it->second) - _popped]));
|
||||
}
|
||||
else { // already in the history
|
||||
return const_cast<Value const*>
|
||||
(&(_history[static_cast<size_t>(-it->second) - 1]));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -166,9 +184,15 @@ namespace triagens {
|
|||
if (it == _lookup.end()) {
|
||||
return false;
|
||||
}
|
||||
size_t pos = it->second - _popped;
|
||||
_heap[pos].setWeight(newWeight);
|
||||
repairUp(pos);
|
||||
if (it->second >= 0) { // still in the queue
|
||||
size_t pos = static_cast<size_t>(it->second) - _popped;
|
||||
_heap[pos].setWeight(newWeight);
|
||||
repairUp(pos);
|
||||
}
|
||||
else { // already in the history
|
||||
size_t pos = static_cast<size_t>(-it->second) - 1;
|
||||
_history[pos].setWeight(newWeight);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -188,18 +212,28 @@ namespace triagens {
|
|||
/// if the structure is empty. Key and Value are stored in k and v.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool popMinimal (Key& k, Value& v) {
|
||||
bool popMinimal (Key& k, Value& v, bool keepForLookup = false) {
|
||||
if (_heap.empty()) {
|
||||
return false;
|
||||
}
|
||||
k = _heap[0].getKey();
|
||||
v = _heap[0];
|
||||
if (! _isHeap) {
|
||||
auto it = _lookup.find(k);
|
||||
TRI_ASSERT(it != _lookup.end());
|
||||
if (keepForLookup) {
|
||||
_history.push_back(_heap[0]);
|
||||
it->second = -static_cast<ssize_t>(_history.size());
|
||||
// Note: This is intentionally one too large to shift by 1
|
||||
}
|
||||
else {
|
||||
_lookup.erase(it);
|
||||
}
|
||||
_heap.pop_front();
|
||||
_popped++;
|
||||
}
|
||||
else {
|
||||
removeFromHeap();
|
||||
removeFromHeap(keepForLookup);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -319,7 +353,7 @@ namespace triagens {
|
|||
/// @brief removeFromHeap, remove first position in the heap
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void removeFromHeap () {
|
||||
void removeFromHeap (bool keepForLookup) {
|
||||
if (_heap.size() == 1) {
|
||||
_heap.clear();
|
||||
_popped = 0;
|
||||
|
@ -331,12 +365,19 @@ namespace triagens {
|
|||
|
||||
auto it = _lookup.find(_heap[0].getKey());
|
||||
TRI_ASSERT(it != _lookup.end());
|
||||
_lookup.erase(it);
|
||||
if (keepForLookup) {
|
||||
_history.push_back(_heap[0]);
|
||||
it->second = -static_cast<ssize_t>(_history.size());
|
||||
// Note: This is intentionally one too large to shift by 1
|
||||
}
|
||||
else {
|
||||
_lookup.erase(it);
|
||||
}
|
||||
_heap[0] = _heap.back();
|
||||
_heap.pop_back();
|
||||
it = _lookup.find(_heap[0].getKey());
|
||||
TRI_ASSERT(it != _lookup.end());
|
||||
it->second = _popped;
|
||||
it->second = static_cast<ssize_t>(_popped);
|
||||
repairDown();
|
||||
}
|
||||
|
||||
|
@ -357,7 +398,7 @@ namespace triagens {
|
|||
/// @brief _lookup, this provides O(1) lookup by Key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unordered_map<Key, size_t> _lookup;
|
||||
std::unordered_map<Key, ssize_t> _lookup;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _isHeap, starts as false, in which case we only use a deque,
|
||||
|
@ -379,6 +420,12 @@ namespace triagens {
|
|||
|
||||
Weight _maxWeight;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _history, the actual data that is only in the key/value store
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<Value> _history;
|
||||
|
||||
};
|
||||
|
||||
class Traverser {
|
||||
|
|
Loading…
Reference in New Issue