/** * @file queue.c * @author guishenking (guishenking@outlook.com) * @brief * @version 0.1 * @date 2025-08-14 * * @copyright Copyright (c) 2025 * */ #include "queue.h" #include #include /** * @brief 初始化队列 * * @param queue * @param elem_size 数据类型大小 */ bool queue_init(queue_t *queue, size_t elem_size) { queue->head = NULL; queue->tail = NULL; queue->size = 0; if(elem_size == 0) { return false; // 元素大小不能为0 } queue->elem_size = elem_size; return true; } /** * @brief 入队 * * @param queue * @param value * @return true * @return false */ bool queue_enqueue(queue_t *queue, const void *value) { // 分配新节点 if (queue->size >= QUEUE_MAX_SIZE) { return false; } queue_node_t *node = (queue_node_t *)malloc(sizeof(queue_node_t)); if (!node) { return false; } // 分配数据空间并复制数据 node->data = malloc(queue->elem_size); // 检查数据分配是否成功 if (!node->data) { // 数据分配失败,此时node还未加入链表,只需释放node本身即可 free(node); return false; } // 复制数据到节点 memcpy(node->data, value, queue->elem_size); // 将下一级节点添加到队列 node->next = NULL; // 如果队列为空,设置头尾指针 if (queue->tail) { // 如果队列不为空,将新节点添加到尾部 queue->tail->next = node; } else { // 如果队列为空,将新节点设置为头部 queue->head = node; } // 更新尾部指针并增加队列大小 queue->tail = node; queue->size++; return true; } /** * @brief 从队列头部出队 * * @param queue * @param value * @return true * @return false */ bool queue_dequeue_head(queue_t *queue, void *value) { // 检查队列是否为空 if (queue->size == 0) { return false; } queue_node_t *node = queue->head; // 复制头部数据到输出参数 memcpy(value, node->data, queue->elem_size); // 更新头部指针 queue->head = node->next; // 如果头部为空,更新尾部指针 if (!queue->head) { queue->tail = NULL; } // 释放节点和数据 free(node->data); free(node); queue->size--; return true; } /** * @brief 从队列尾部出队 * * @param queue * @param value * @return true * @return false */ bool queue_dequeue_tail(queue_t *queue, void *value) { if (queue->size == 0) { return false; } queue_node_t *prev = NULL; queue_node_t *node = queue->head; // 找到最后一个节点 while (node && node->next) { prev = node; node = node->next; } memcpy(value, node->data, queue->elem_size); if (prev) { prev->next = NULL; queue->tail = prev; } else { // 只有一个节点 queue->head = NULL; queue->tail = NULL; } free(node->data); free(node); queue->size--; return true; } /** * @brief 查询队列指定位置的数据 * * @param queue 队列指针 * @param index 位置(0为头部) * @param value 输出数据指针 * @return true 查询成功 * @return false 越界或队列为空 */ bool queue_peek_at(const queue_t *queue, size_t index, void *value) { if (index >= queue->size || queue->size == 0) { return false; // 越界或队列为空 } queue_node_t *node = queue->head; for (size_t i = 0; i < index; ++i) { node = node->next; } memcpy(value, node->data, queue->elem_size); return true; } /** * @brief 抛弃队列前n个数据 * * @param queue 队列指针 * @param n 要抛弃的元素数量 * @return size_t 实际抛弃的元素数量 */ size_t queue_drop_head(queue_t *queue, size_t n) { size_t dropped = 0; if (n == 0 || queue->size == 0) { return 0; } if (n >= queue->size) { dropped = queue->size; queue_clear(queue); return dropped; } while (dropped < n && queue->size > 0) { queue_node_t *node = queue->head; queue->head = node->next; free(node->data); free(node); queue->size--; dropped++; } if (!queue->head) { queue->tail = NULL; } return dropped; } /** * @brief 抛弃队列尾部n个数据 * * @param queue 队列指针 * @param n 要抛弃的元素数量 * @return size_t 实际抛弃的元素数量 */ size_t queue_drop_tail(queue_t *queue, size_t n) { size_t dropped = 0; if (n == 0 || queue->size == 0) { return 0; } if (n >= queue->size) { // 清空整个队列 dropped = queue->size; queue_clear(queue); return dropped; } for (size_t i = 0; i < n; ++i) { queue_node_t *prev = NULL; queue_node_t *node = queue->head; // 找到最后一个节点 while (node && node->next) { prev = node; node = node->next; } if (!node) break; if (prev) { prev->next = NULL; queue->tail = prev; } else { // 只有一个节点 queue->head = NULL; queue->tail = NULL; } free(node->data); free(node); queue->size--; dropped++; } return dropped; } /** * @brief 判断队列是否为空 * * @param queue * @return true * @return false */ bool queue_is_empty(const queue_t *queue) { return queue->size == 0; } /** * @brief 获取队列长度 * * @param queue * @return size_t */ size_t queue_length(const queue_t *queue) { return queue->size; } /** * @brief 清空队列 * * @param queue */ void queue_clear(queue_t *queue) { queue_node_t *node = queue->head; while (node) { queue_node_t *next = node->next; free(node->data); free(node); node = next; } queue->head = NULL; queue->tail = NULL; queue->size = 0; } /** * @brief 销毁队列 * * @param queue */ void queue_destroy(queue_t *queue) { queue_clear(queue); // 如果有其他资源分配,可在此释放 }