comments, al .md done
This commit is contained in:
@@ -7,35 +7,76 @@
|
|||||||
#include <format>
|
#include <format>
|
||||||
#include <expected>
|
#include <expected>
|
||||||
|
|
||||||
|
/// @brief Default initial capacity for the queue
|
||||||
#define DEFAULT_QUEUE_SIZE 4
|
#define DEFAULT_QUEUE_SIZE 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum QueueErr
|
||||||
|
* @brief Represents possible error states for queue operations
|
||||||
|
*/
|
||||||
enum class QueueErr {
|
enum class QueueErr {
|
||||||
ok,
|
ok, ///< Operation successful
|
||||||
bad_alloc,
|
bad_alloc, ///< Memory allocation failed
|
||||||
empty,
|
empty, ///< Queue is empty
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Queue
|
||||||
|
* @brief A dynamically resizing circular queue implementation
|
||||||
|
*
|
||||||
|
* @tparam T Type of elements stored in the queue. Must be formattable.
|
||||||
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::formattable<T, char>
|
requires std::formattable<T, char>
|
||||||
class Queue {
|
class Queue {
|
||||||
private:
|
private:
|
||||||
uint64_t len;
|
uint64_t len; ///< Current number of elements
|
||||||
uint64_t cap;
|
uint64_t cap; ///< Current capacity
|
||||||
uint64_t head;
|
uint64_t head; ///< Index of next insertion
|
||||||
uint64_t tail;
|
uint64_t tail; ///< Index of next removal
|
||||||
T *data;
|
T *data; ///< Pointer to dynamically allocated array
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Default constructor
|
||||||
|
* Initializes the queue with DEFAULT_QUEUE_SIZE capacity
|
||||||
|
*/
|
||||||
Queue();
|
Queue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor with custom size
|
||||||
|
* @param size Initial capacity of the queue
|
||||||
|
*/
|
||||||
Queue(uint64_t size);
|
Queue(uint64_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
* Frees allocated memory
|
||||||
|
*/
|
||||||
~Queue();
|
~Queue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inserts an element at the end of the queue
|
||||||
|
* @param value Value to insert
|
||||||
|
* @return QueueErr Status of the operation
|
||||||
|
*/
|
||||||
QueueErr enqueue(T value);
|
QueueErr enqueue(T value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the front element without removing it
|
||||||
|
* @return std::expected<T, QueueErr> Value or error if empty
|
||||||
|
*/
|
||||||
std::expected<T, QueueErr> peek();
|
std::expected<T, QueueErr> peek();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes and returns the front element
|
||||||
|
* @return std::expected<T, QueueErr> Value or error if empty
|
||||||
|
*/
|
||||||
std::expected<T, QueueErr> dequeue();
|
std::expected<T, QueueErr> dequeue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints a visual representation of the queue
|
||||||
|
*/
|
||||||
void print();
|
void print();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -52,12 +93,11 @@ Queue<T>::Queue() {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::formattable<T, char>
|
requires std::formattable<T, char>
|
||||||
Queue<T>::Queue(uint64_t size) {
|
Queue<T>::Queue(uint64_t size) {
|
||||||
this->cap = DEFAULT_QUEUE_SIZE;
|
this->cap = size;
|
||||||
this->len = 0;
|
this->len = 0;
|
||||||
this->head = 0;
|
this->head = 0;
|
||||||
this->tail = 0;
|
this->tail = 0;
|
||||||
this->data = new T[size];
|
this->data = new T[size];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -70,10 +110,10 @@ Queue<T>::~Queue() {
|
|||||||
this->tail = 0;
|
this->tail = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::formattable<T, char>
|
requires std::formattable<T, char>
|
||||||
QueueErr Queue<T>::enqueue(T value) {
|
QueueErr Queue<T>::enqueue(T value) {
|
||||||
|
/// Resize if needed
|
||||||
if (this->len >= this->cap) {
|
if (this->len >= this->cap) {
|
||||||
uint64_t new_cap = this->cap * 2;
|
uint64_t new_cap = this->cap * 2;
|
||||||
T *tmp;
|
T *tmp;
|
||||||
@@ -84,6 +124,7 @@ QueueErr Queue<T>::enqueue(T value) {
|
|||||||
return QueueErr::bad_alloc;
|
return QueueErr::bad_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Copy elements in correct order
|
||||||
for (uint64_t i = 0; i < this->len; i++) {
|
for (uint64_t i = 0; i < this->len; i++) {
|
||||||
uint64_t index = (this->tail + i) % this->cap;
|
uint64_t index = (this->tail + i) % this->cap;
|
||||||
tmp[i] = this->data[index];
|
tmp[i] = this->data[index];
|
||||||
@@ -99,16 +140,19 @@ QueueErr Queue<T>::enqueue(T value) {
|
|||||||
this->data[this->head] = value;
|
this->data[this->head] = value;
|
||||||
this->len++;
|
this->len++;
|
||||||
this->head = (this->head + 1) % this->cap;
|
this->head = (this->head + 1) % this->cap;
|
||||||
|
|
||||||
return QueueErr::ok;
|
return QueueErr::ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::formattable<T, char>
|
requires std::formattable<T, char>
|
||||||
std::expected<T, QueueErr> Queue<T>::dequeue() {
|
std::expected<T, QueueErr> Queue<T>::dequeue() {
|
||||||
|
/// Check if empty
|
||||||
if (this->len == 0) {
|
if (this->len == 0) {
|
||||||
return std::unexpected(QueueErr::empty);
|
return std::unexpected(QueueErr::empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shrink if too sparse
|
||||||
if (this->cap > DEFAULT_QUEUE_SIZE && this->cap / 4 > this->len) {
|
if (this->cap > DEFAULT_QUEUE_SIZE && this->cap / 4 > this->len) {
|
||||||
uint64_t new_cap = this->cap / 2;
|
uint64_t new_cap = this->cap / 2;
|
||||||
if (new_cap < DEFAULT_QUEUE_SIZE) {
|
if (new_cap < DEFAULT_QUEUE_SIZE) {
|
||||||
@@ -122,6 +166,7 @@ std::expected<T, QueueErr> Queue<T>::dequeue() {
|
|||||||
return std::unexpected(QueueErr::bad_alloc);
|
return std::unexpected(QueueErr::bad_alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Copy elements
|
||||||
for (uint64_t i = 0; i < this->len; i++) {
|
for (uint64_t i = 0; i < this->len; i++) {
|
||||||
uint64_t index = (this->tail + i) % this->cap;
|
uint64_t index = (this->tail + i) % this->cap;
|
||||||
tmp[i] = this->data[index];
|
tmp[i] = this->data[index];
|
||||||
@@ -132,11 +177,10 @@ std::expected<T, QueueErr> Queue<T>::dequeue() {
|
|||||||
this->cap = new_cap;
|
this->cap = new_cap;
|
||||||
this->tail = 0;
|
this->tail = 0;
|
||||||
this->head = this->len;
|
this->head = this->len;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
T out;
|
T out = this->data[this->tail];
|
||||||
out = this->data[this->tail];
|
|
||||||
this->len--;
|
this->len--;
|
||||||
this->tail = (this->tail + 1) % this->cap;
|
this->tail = (this->tail + 1) % this->cap;
|
||||||
|
|
||||||
@@ -146,18 +190,18 @@ std::expected<T, QueueErr> Queue<T>::dequeue() {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::formattable<T, char>
|
requires std::formattable<T, char>
|
||||||
std::expected<T, QueueErr> Queue<T>::peek() {
|
std::expected<T, QueueErr> Queue<T>::peek() {
|
||||||
|
/// Check if empty
|
||||||
if (this->len == 0) {
|
if (this->len == 0) {
|
||||||
return std::unexpected(QueueErr::empty);
|
return std::unexpected(QueueErr::empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
T out;
|
return this->data[this->tail];
|
||||||
out = this->data[this->tail];
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::formattable<T, char>
|
requires std::formattable<T, char>
|
||||||
void Queue<T>::print() {
|
void Queue<T>::print() {
|
||||||
|
/// Print queue state
|
||||||
if (this->len == 0) {
|
if (this->len == 0) {
|
||||||
std::println("Queue is empty.");
|
std::println("Queue is empty.");
|
||||||
return;
|
return;
|
||||||
@@ -186,4 +230,5 @@ void Queue<T>::print() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !QUEUE_H
|
#endif // !QUEUE_H
|
||||||
|
|||||||
Reference in New Issue
Block a user