mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-04 23:19:27 +00:00
AK: Store BinaryHeap key-value pairs together for efficient swaps
The 2 seperate key and value arrays are replaced with a single struct pair array that allows for a 2x reduction in loads/stores during element swaps in the common case of same-sized keys and values.
This commit is contained in:
parent
161b36bb09
commit
3c7aa56ae8
|
@ -39,8 +39,10 @@ public:
|
||||||
{
|
{
|
||||||
VERIFY(size <= Capacity);
|
VERIFY(size <= Capacity);
|
||||||
m_size = size;
|
m_size = size;
|
||||||
__builtin_memcpy(m_keys, keys, size * sizeof(K));
|
for (size_t i = 0; i < size; i++) {
|
||||||
__builtin_memcpy(m_values, values, size * sizeof(V));
|
m_elements[i].key = keys[i];
|
||||||
|
m_elements[i].value = values[i];
|
||||||
|
}
|
||||||
|
|
||||||
for (ssize_t i = size / 2; i >= 0; i--) {
|
for (ssize_t i = size / 2; i >= 0; i--) {
|
||||||
heapify_down(i);
|
heapify_down(i);
|
||||||
|
@ -54,8 +56,8 @@ public:
|
||||||
{
|
{
|
||||||
VERIFY(m_size < Capacity);
|
VERIFY(m_size < Capacity);
|
||||||
auto index = m_size++;
|
auto index = m_size++;
|
||||||
m_keys[index] = key;
|
m_elements[index].key = key;
|
||||||
m_values[index] = value;
|
m_elements[index].value = value;
|
||||||
heapify_up(index);
|
heapify_up(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,22 +65,21 @@ public:
|
||||||
{
|
{
|
||||||
VERIFY(!is_empty());
|
VERIFY(!is_empty());
|
||||||
auto index = --m_size;
|
auto index = --m_size;
|
||||||
swap(m_keys[0], m_keys[index]);
|
swap(m_elements[0], m_elements[index]);
|
||||||
swap(m_values[0], m_values[index]);
|
|
||||||
heapify_down(0);
|
heapify_down(0);
|
||||||
return m_values[index];
|
return m_elements[index].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const V& peek_min() const
|
const V& peek_min() const
|
||||||
{
|
{
|
||||||
VERIFY(!is_empty());
|
VERIFY(!is_empty());
|
||||||
return m_values[0];
|
return m_elements[0].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const V& peek_min_key() const
|
const K& peek_min_key() const
|
||||||
{
|
{
|
||||||
VERIFY(!is_empty());
|
VERIFY(!is_empty());
|
||||||
return m_keys[0];
|
return m_elements[0].key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
|
@ -94,13 +95,12 @@ private:
|
||||||
auto right_child = index * 2 + 2;
|
auto right_child = index * 2 + 2;
|
||||||
|
|
||||||
auto min_child = left_child;
|
auto min_child = left_child;
|
||||||
if (right_child < m_size && m_keys[right_child] < m_keys[min_child])
|
if (right_child < m_size && m_elements[right_child].key < m_elements[min_child].key)
|
||||||
min_child = right_child;
|
min_child = right_child;
|
||||||
|
|
||||||
if (m_keys[index] <= m_keys[min_child])
|
if (m_elements[index].key <= m_elements[min_child].key)
|
||||||
break;
|
break;
|
||||||
swap(m_keys[index], m_keys[min_child]);
|
swap(m_elements[index], m_elements[min_child]);
|
||||||
swap(m_values[index], m_values[min_child]);
|
|
||||||
index = min_child;
|
index = min_child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,16 +110,17 @@ private:
|
||||||
while (index != 0) {
|
while (index != 0) {
|
||||||
auto parent = (index - 1) / 2;
|
auto parent = (index - 1) / 2;
|
||||||
|
|
||||||
if (m_keys[index] >= m_keys[parent])
|
if (m_elements[index].key >= m_elements[parent].key)
|
||||||
break;
|
break;
|
||||||
swap(m_keys[index], m_keys[parent]);
|
swap(m_elements[index], m_elements[parent]);
|
||||||
swap(m_values[index], m_values[parent]);
|
|
||||||
index = parent;
|
index = parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
K m_keys[Capacity];
|
struct {
|
||||||
V m_values[Capacity];
|
K key;
|
||||||
|
V value;
|
||||||
|
} m_elements[Capacity];
|
||||||
size_t m_size { 0 };
|
size_t m_size { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue