diff --git a/include/blt/std/queue.h b/include/blt/std/queue.h index a447f47..49e32f2 100644 --- a/include/blt/std/queue.h +++ b/include/blt/std/queue.h @@ -8,21 +8,10 @@ #define BLT_QUEUE_H /** - * Do no use any queue in this file. They are slower than std::queue. + * */ namespace blt { - template<typename T> - struct node { - T t; - node* next; - - node(const T& t, node* next) { - this->t = t; - this->next = next; - } - }; - /** * Standard array backed first in first out queue * @tparam T type stored in the queue @@ -39,20 +28,21 @@ namespace blt { * and deletes the old array from memory. * @param newSize new size of the internal array */ - void expand(int newSize) { - auto tempData = new T[newSize]; + void expand() { + int new_size = m_size * 2; + auto tempData = new T[new_size]; for (int i = 0; i < m_insertIndex; i++) tempData[i] = m_data[i]; delete[] m_data; m_data = tempData; - m_size = newSize; + m_size = new_size; } public: void push(const T& t) { if (m_insertIndex >= m_size) { - expand(m_size * 2); + expand(); } m_data[m_insertIndex++] = t; } @@ -66,8 +56,6 @@ namespace blt { } void pop() { - // TODO: throw exception when popping would result in a overflow? - // I didn't make it an exception here due to not wanting to import the class. if (isEmpty()) return; m_insertIndex--; @@ -96,29 +84,32 @@ namespace blt { int m_size = 16; int m_headIndex = 0; int m_insertIndex = 0; - T* m_data = new T[m_size]; - + T* m_data; /** - * Expands the internal array to the new size, copying over the data and shifting its minimal position to index 0 - * and deletes the old array from memory. - * @param newSize new size of the internal array + * Expands the internal array to allow for more storage of elements */ - void expand(int newSize) { - auto tempData = new T[newSize]; - for (int i = 0; i < m_size - m_headIndex; i++) - tempData[i] = m_data[i + m_headIndex]; + void expand() { + int new_size = m_size * 2; + int removed_size = m_size - m_headIndex; + auto tempData = new T[new_size]; + // only copy data from where we've removed onward + for (int i = 0; i < removed_size; i++) + tempData[i] = m_data[i + m_headIndex]; // but don't copy data we've pop'd delete[] m_data; - m_insertIndex = m_size - m_headIndex; m_headIndex = 0; + m_insertIndex = removed_size - 1; m_data = tempData; - m_size = newSize; + m_size = new_size; } public: + flat_queue(): m_data(new T[m_size]) { + + } void push(const T& t) { if (m_insertIndex+1 >= m_size) { - expand(m_size * 2); + expand(); } m_data[m_insertIndex++] = t; } @@ -132,8 +123,6 @@ namespace blt { } void pop() { - // TODO: throw exception when popping would result in a overflow? - // I didn't make it an exception here due to not wanting to import the class. if (isEmpty()) return; m_headIndex++; @@ -159,40 +148,6 @@ namespace blt { delete[](m_data); } }; - - // avoid this. it is very slow. - template<typename T> - class node_queue { - private: - node<T>* m_head; - public: - - void push(const T& t) { - if (m_head == nullptr) - m_head = new node<T>(t, nullptr); - else - m_head = new node<T>(t, m_head); - } - - [[nodiscard]] const T& front() const { - return m_head->t; - } - - void pop() { - auto nextNode = m_head->next; - delete (m_head); - m_head = nextNode; - } - - ~node_queue() { - auto next = m_head; - while (next != nullptr) { - auto nextNode = next->next; - delete (next); - next = nextNode; - } - } - }; } #endif //BLT_QUEUE_H diff --git a/src/tests/queue_tests.h b/src/tests/queue_tests.h index b7e83a0..c78fb3c 100644 --- a/src/tests/queue_tests.h +++ b/src/tests/queue_tests.h @@ -14,12 +14,11 @@ #include <array> #include <blt/std/random.h> -std::array<int, 100000> values{}; +std::array<int, 15000> values{}; std::queue<int> base_queue{}; blt::flat_queue<int> blt_flat_queue{}; blt::flat_stack<int> blt_flat_stack{}; -blt::node_queue<int> blt_node_queue{}; static inline void fill_queues(){ BLT_START_INTERVAL("Insert", "std::queue"); @@ -36,17 +35,11 @@ static inline void fill_queues(){ for (const auto& value : values) blt_flat_stack.push(value); BLT_END_INTERVAL("Insert", "blt::flat_stack"); - - BLT_START_INTERVAL("Insert", "blt::node_queue"); - for (const auto& value : values) - blt_node_queue.push(value); - BLT_END_INTERVAL("Insert", "blt::node_queue"); } static inline void validate(){ bool std_valid = true; bool flat_valid = true; - bool node_valid = true; bool stack_valid = true; BLT_START_INTERVAL("Access", "std::queue"); for (const auto& value : values) { @@ -69,37 +62,74 @@ static inline void validate(){ BLT_END_INTERVAL("Access", "blt::flat_queue"); BLT_START_INTERVAL("Access", "blt::flat_stack"); - for (const auto& value : values) { + for (int i = values.size()-1; i > 0; i--) { + const auto& value = values[i]; auto front = blt_flat_stack.top(); - + if (front != value) stack_valid = false; + blt_flat_stack.pop(); } BLT_END_INTERVAL("Access", "blt::flat_stack"); - BLT_START_INTERVAL("Access", "blt::node_queue"); - for (const auto& value : values) { - auto front = blt_node_queue.front(); - - if (front != value) - node_valid = false; - blt_node_queue.pop(); - } - BLT_END_INTERVAL("Access", "blt::node_queue"); - if (!std_valid) BLT_ERROR("std::queue invalid!"); if (!flat_valid) BLT_ERROR("blt::flat_queue invalid!"); - if (!node_valid) - BLT_ERROR("blt::node_queue invalid!"); + if (!stack_valid) + BLT_ERROR("blt::stack invalid!"); +} + +static inline void random_access() { + bool flat_valid = true; + bool stack_valid = true; + + BLT_START_INTERVAL("Access", "blt::flat_queue"); + for (int i = 0; i < 500; i++) { + auto front = blt_flat_queue.front(); + auto next = base_queue.front(); + + if (front != next) + flat_valid = false; + blt_flat_queue.pop(); + base_queue.pop(); + } + for (int value : values){ + blt_flat_queue.push(value); + base_queue.push(value); + } + for (int i = 0; i < values.size(); i++) { + auto front = blt_flat_queue.front(); + auto next = base_queue.front(); + + if (front != next) + flat_valid = false; + blt_flat_queue.pop(); + base_queue.pop(); + } + BLT_END_INTERVAL("Random", "blt::flat_queue"); + + BLT_START_INTERVAL("Random", "blt::flat_stack"); + for (int i = values.size()-1; i > 0; i--) { + const auto& value = values[i]; + auto front = blt_flat_stack.top(); + + if (front != value) + stack_valid = false; + + blt_flat_stack.pop(); + } + BLT_END_INTERVAL("Random", "blt::flat_stack"); + + if (!flat_valid) + BLT_ERROR("blt::flat_queue invalid!"); if (!stack_valid) BLT_ERROR("blt::stack invalid!"); } static inline void test_queues() { - blt::random<int, std::uniform_int_distribution> rand{1, std::numeric_limits<int>::max()}; + blt::random<int, std::uniform_int_distribution> rand{1, 100}; for (int& value : values){ value = rand.get(); @@ -107,10 +137,12 @@ static inline void test_queues() { fill_queues(); validate(); - + fill_queues(); + random_access(); BLT_PRINT_PROFILE("Insert", blt::logging::LOG_LEVEL::INFO, true); BLT_PRINT_PROFILE("Access", blt::logging::LOG_LEVEL::INFO, true); + BLT_PRINT_PROFILE("Random", blt::logging::LOG_LEVEL::INFO, true); } #endif //BLT_TESTS_QUEUE_TESTS_H