main
parent
ef79633f1a
commit
9d4fd5a082
|
@ -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
|
|
@ -0,0 +1,136 @@
|
|||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#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);
|
||||
}
|
Loading…
Reference in New Issue