Skip to content

Commit

Permalink
Merge pull request #12 from coopsdev/fix-resize
Browse files Browse the repository at this point in the history
Fix resize()
  • Loading branch information
cooperlarson authored Aug 5, 2024
2 parents bc2b8cc + 0117091 commit c996946
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 20 deletions.
55 changes: 35 additions & 20 deletions include/BoundedPriorityDeque.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,14 @@ class BoundedPriorityDequeBase {
* @return The optimal insertion index for the targeted insertion element.
*/
size_t binarySearch(const BoundingPair<K, V>& target) const {
auto start = _head;
auto end = start + _size;
size_t start = 0;
auto end = _size;
while (start != end) {
size_t mid = (start + (end - start) / 2) % _k;
if (compare(_buffer[mid].key, target.key)) start = (mid + 1) % _k;
size_t mid = start + (end - start) / 2;
if (compare(_buffer[(_head + mid) % _k].key, target.key)) start = mid + 1;
else end = mid;
}
return start;
return (_head + start) % _k;
}

/**
Expand All @@ -163,13 +163,17 @@ class BoundedPriorityDequeBase {
}

auto index = binarySearch(element);
if (index != nextIndex(_tail)) {
if (_head > 0) std::move(_buffer.begin() + _head, _buffer.begin() + index + 1, _buffer.begin() + _head - 1);
else std::move_backward(_buffer.begin() + index, _buffer.begin() + _tail + 1, _buffer.begin() + _tail + 2);
if (index == nextIndex(_tail)) _tail = nextIndex(_tail);
else if (index == prevIndex(_head)) _head = prevIndex(_head);
else if (_head <= _tail && _head > 0) {
std::move(_buffer.begin() + _head, _buffer.begin() + index + 1, _buffer.begin() + _head - 1);
--_head;
} else {
std::move_backward(_buffer.begin() + index, _buffer.begin() + _tail + 1, _buffer.begin() + _tail + 2);
++_tail;
}

_buffer[index] = element;
_tail = nextIndex(_tail);
++_size;
}

Expand Down Expand Up @@ -377,19 +381,30 @@ class BoundedPriorityDequeBase {
* @param k The new capacity.
*/
void resize(size_t k) {
_k = k;
if (k == 0) return;

std::vector<BoundingPair<K, V>> newBuffer(k);

if (_head <= _tail) {
if (_head > 0) std::move(_buffer.begin() + _head, _buffer.begin() + _tail + 1, _buffer.begin());
_buffer.resize(_k);
}
else {
std::vector<BoundingPair<K, V>> newBuffer(_k);
std::move(_buffer.begin() + _head, _buffer.end() + 1, newBuffer.begin());
std::move(_buffer.begin(), _buffer.begin() + _tail + 1, newBuffer.begin() + (_k - _head - 1));
_buffer = newBuffer;
_head = 0;
_tail = _size - 1;
size_t elementsToCopy = std::min(_size, k);
std::move(_buffer.begin() + _head, _buffer.begin() + _head + elementsToCopy, newBuffer.begin());
_size = elementsToCopy;
} else {
size_t topSize = _k - _head;
size_t bottomSize = _tail + 1;
size_t elementsToCopyTop = std::min(topSize, k);
size_t elementsToCopyBottom = std::min(bottomSize, k - elementsToCopyTop);

std::move(_buffer.begin() + _head, _buffer.begin() + _head + elementsToCopyTop, newBuffer.begin());
std::move(_buffer.begin(), _buffer.begin() + elementsToCopyBottom, newBuffer.begin() + elementsToCopyTop);

_size = elementsToCopyTop + elementsToCopyBottom;
}

_buffer.swap(newBuffer);
_k = k;
_head = 0;
_tail = _size - 1;
}
};

Expand Down
64 changes: 64 additions & 0 deletions test/deque_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,70 @@ TEST(BoundedDequeTest, Merge) {
ASSERT_TRUE(a.empty());
}

TEST(BoundedDequeTest, Resize) {
BoundedMinPriorityDeque<int, std::string> deque(5);
deque.emplace(2, "two");
deque.emplace(5, "five");
deque.emplace(7, "seven");
deque.emplace(12, "twelve");

auto two = deque.pop();
deque.resize(2);
ASSERT_EQ(deque.topK(), 5);
ASSERT_EQ(deque.bottomK(), 7);
deque.pop();

deque.resize(4);
deque.emplace(1, "one");
deque.emplace(3, "three");
deque.emplace(9, "nine");
deque.emplace(4, "four");
deque.push(two);
deque.resize(4);

ASSERT_EQ(deque.pop().value, "one");
ASSERT_EQ(deque.pop().value, "two");
ASSERT_EQ(deque.pop().value, "three");
ASSERT_EQ(deque.pop().value, "four");
ASSERT_TRUE(deque.empty());
}

TEST(BoundedDequeTest, ResizeCircular) {
// Initialize the buffer with a capacity of 5
BoundedMinPriorityDeque<int, std::string> deque(5);

// Fill the buffer
deque.emplace(5, "five");
deque.emplace(10, "ten");
deque.emplace(15, "fifteen");
deque.emplace(20, "twenty");
deque.emplace(25, "twenty-five");

// Pop three elements to move the head forward
ASSERT_EQ(deque.pop().value, "five");
ASSERT_EQ(deque.pop().value, "ten");
ASSERT_EQ(deque.pop().value, "fifteen");

// Check current state of the deque
ASSERT_EQ(deque.size(), 2);

// Continue pushing elements
deque.emplace(47, "forty-seven");
deque.emplace(53, "fifty-three");
deque.emplace(43, "forty-three");

// Resize the deque while it is wrapped around
deque.resize(4);

// Validate the contents and order after resizing
ASSERT_EQ(deque.size(), 4);
ASSERT_EQ(deque.pop().key, 20);
ASSERT_EQ(deque.pop().key, 25);
ASSERT_EQ(deque.pop().key, 43);
ASSERT_EQ(deque.pop().key, 47);
ASSERT_TRUE(deque.empty());
}

class ConcurrentDequeTest : public ::testing::Test {
protected:
BoundedMinPriorityDeque<int, std::string> deque;
Expand Down

0 comments on commit c996946

Please sign in to comment.