diff --git a/lib/inc/list/queue.h b/lib/inc/list/queue.h new file mode 100644 index 0000000..5434169 --- /dev/null +++ b/lib/inc/list/queue.h @@ -0,0 +1,118 @@ +#ifndef HW_LIB_QUEUE_H +#define HW_LIB_QUEUE_H +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief 双向链表节点结构体 + */ +typedef struct DoublyListNode { + void *val; // 节点值 + struct DoublyListNode *next; // 后继节点 + struct DoublyListNode *prev; // 前驱节点 +} DoublyListNode; + +/** + * @brief 双端队列结构体 + */ +typedef struct { + DoublyListNode *front, *rear; // 头节点 front ,尾节点 rear + int queSize; // 双向队列的长度 +} LinkedListDeque; + +/** + * @brief 创建一个新的双端队列 + * @return LinkedListDeque* 返回新创建的双端队列指针 + * @example deque = newLinkedListDeque(); + */ +extern LinkedListDeque *newLinkedListDeque(); + +/** + * @brief 销毁双端队列 + * @param deque: [输入] 双端队列指针 + * @return void + * @example delLinkedListdeque(deque); + */ +extern void delLinkedListdeque(LinkedListDeque *deque); + +/** + * @brief 获取队列大小 + * @param deque: [输入] 双端队列指针 + * @return int 返回队列中元素个数 + * @example size = queue_size(deque); + */ +extern int queue_size(LinkedListDeque *deque); + +/** + * @brief 检查队列是否为空 + * @param deque: [输入] 双端队列指针 + * @return bool 若队列为空返回true,否则返回false + * @example if (queue_is_empty(deque)) { // do something } + */ +extern bool queue_is_empty(LinkedListDeque *deque); + +/** + * @brief 在队列头部插入元素 + * @param deque: [输入] 双端队列指针 + * @param data: [输入] 待插入的数据指针 + * @return void + * @example pushFirst(deque, newData); + */ +extern void pushFirst(LinkedListDeque *deque, void *data); + +/** + * @brief 在队列尾部插入元素 + * @param deque: [输入] 双端队列指针 + * @param data: [输入] 待插入的数据指针 + * @return void + * @example pushLast(deque, newData); + */ +extern void pushLast(LinkedListDeque *deque, void *data); + +/** + * @brief 获取队列头部元素但不移除 + * @param deque: [输入] 双端队列指针 + * @return void* 返回队列头部元素的指针,若队列为空返回NULL + * @example firstData = peekFirst(deque); + */ +extern void *peekFirst(LinkedListDeque *deque); + +/** + * @brief 获取队列尾部元素但不移除 + * @param deque: [输入] 双端队列指针 + * @return void* 返回队列尾部元素的指针,若队列为空返回NULL + * @example lastData = peekLast(deque); + */ +extern void *peekLast(LinkedListDeque *deque); + +/** + * @brief 弹出队列头部或尾部元素 + * @param deque: [输入] 双端队列指针 + * @param isFront: [输入] 若为true则从头部弹出,否则从尾部弹出 + * @return void* 返回被弹出元素的指针,若队列为空返回NULL + * @example poppedData = pop(deque, true); + */ +extern void *pop(LinkedListDeque *deque, bool isFront); + +/** + * @brief 弹出队列头部元素 + * @param deque: [输入] 双端队列指针 + * @return void* 返回被弹出的头部元素的指针,若队列为空返回NULL + * @example poppedData = popFirst(deque); + */ +extern void *popFirst(LinkedListDeque *deque); + +/** + * @brief 弹出队列尾部元素 + * @param deque: [输入] 双端队列指针 + * @return void* 返回被弹出的尾部元素的指针,若队列为空返回NULL + * @example poppedData = popLast(deque); + */ +extern void *popLast(LinkedListDeque *deque); + + +#ifdef __cplusplus +} +#endif +#endif //HW_LIB_QUEUE_H diff --git a/lib/src/list/queue.cpp b/lib/src/list/queue.cpp new file mode 100644 index 0000000..b1603f4 --- /dev/null +++ b/lib/src/list/queue.cpp @@ -0,0 +1,136 @@ +#include +#include +#include "queue.h" + + +DoublyListNode *newDoublyListNode(void *data) { + DoublyListNode *node = (DoublyListNode *) malloc(sizeof(DoublyListNode)); + node->val = data; + node->next = NULL; + node->prev = NULL; + return node; +} + +/* 析构函数 */ +void delDoublyListNode(DoublyListNode *node) { + free(node); +} + + +/* 构造函数 */ +LinkedListDeque *newLinkedListDeque() { + LinkedListDeque *deque = (LinkedListDeque *) malloc(sizeof(LinkedListDeque)); + deque->front = NULL; + deque->rear = NULL; + deque->queSize = 0; + return deque; +} + +/* 析构函数 */ +void delLinkedListdeque(LinkedListDeque *deque) { + // 释放所有节点 + for (int i = 0; i < deque->queSize && deque->front != NULL; i++) { + DoublyListNode *tmp = deque->front; + deque->front = deque->front->next; + free(tmp); + } + // 释放 deque 结构体 + free(deque); +} + +/* 获取队列的长度 */ +int queue_size(LinkedListDeque *deque) { + return deque->queSize; +} + +/* 判断队列是否为空 */ +bool queue_is_empty(LinkedListDeque *deque) { + return (queue_size(deque) == 0); +} + +/* 入队 */ +void push(LinkedListDeque *deque, void *data, bool isFront) { + DoublyListNode *node = newDoublyListNode(data); + // 若链表为空,则令 front 和 rear 都指向node + if (queue_is_empty(deque)) { + deque->front = deque->rear = node; + } + // 队首入队操作 + else if (isFront) { + // 将 node 添加至链表头部 + deque->front->prev = node; + node->next = deque->front; + deque->front = node; // 更新头节点 + } + // 队尾入队操作 + else { + // 将 node 添加至链表尾部 + deque->rear->next = node; + node->prev = deque->rear; + deque->rear = node; + } + deque->queSize++; // 更新队列长度 +} + +/* 队首入队 */ +void pushFirst(LinkedListDeque *deque, void *data) { + push(deque, data, true); +} + +/* 队尾入队 */ +void pushLast(LinkedListDeque *deque, void *data) { + push(deque, data, false); +} + +/* 访问队首元素 */ +void *peekFirst(LinkedListDeque *deque) { + assert(queue_size(deque) && deque->front); + return deque->front->val; +} + +/* 访问队尾元素 */ +void *peekLast(LinkedListDeque *deque) { + assert(queue_size(deque) && deque->rear); + return deque->rear->val; +} + +/* 出队 */ +void *pop(LinkedListDeque *deque, bool isFront) { + if (queue_is_empty(deque)) + return nullptr; + void *val; + // 队首出队操作 + if (isFront) { + val = peekFirst(deque); // 暂存头节点值 + DoublyListNode *fNext = deque->front->next; + if (fNext) { + fNext->prev = NULL; + deque->front->next = NULL; + } + delDoublyListNode(deque->front); + deque->front = fNext; // 更新头节点 + } + // 队尾出队操作 + else { + val = peekLast(deque); // 暂存尾节点值 + DoublyListNode *rPrev = deque->rear->prev; + if (rPrev) { + rPrev->next = NULL; + deque->rear->prev = NULL; + } + delDoublyListNode(deque->rear); + deque->rear = rPrev; // 更新尾节点 + } + deque->queSize--; // 更新队列长度 + return val; +} + +/* 队首出队 */ +void *popFirst(LinkedListDeque *deque) { + return pop(deque, true); +} + +/* 队尾出队 */ +void *popLast(LinkedListDeque *deque) { + return pop(deque, false); +} \ No newline at end of file