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