文章目录
队列
定义
-
FIFO LILO
-
先进先出,后进后出
-
循环队列 顺序队列
-
链式队列
比较循环队列和链式队列
项目 | 循环队列 | 链式队列 |
---|---|---|
插入和删除时间复杂度 | O(1) | o(1) |
是否会满 | 是 | 否 |
链式队列实现
结构体定义
struct _QNode {
struct _QNode *next;
char elem[];
};
#define _QNODESIZE sizeof(struct _QNode)
struct Queue {
size_t elemSize; // 存储元素类型字节数
size_t size;
struct _QNode *head; // 指向队列首
struct _QNode *tail; // 指向队列尾
};
typedef struct Queue* QE;
基础函数声明
// 创建空队列
QE create_queue(size_t elemSize);
// 销毁队列
void destroy_queue(QE q);
// 清空队列
void clear_queue(QE q);
// 队列中元素个数
size_t size_queue(QE q);
// 判断队列是否为空
bool empty_queue(QE q);
// 压入队尾
int push_queue(QE q, const void *pElem);
// 从队头弹出
int pop_queue(QE q, void *pElem);
// 获取队头元素
int front_queue(QE q, void *pElem);
// 获取队尾元素
int back_queue(QE q, void *pElem);
//迭代
void foreach_queue(QE q, void (*foreach)(const void*));
基础函数实现
创建空队列 create_queue
QE create_queue(size_t elemSize)
{
QE q = (QE)malloc(sizeof(struct Queue)); // 创建空队列
if (q != NULL) {
q->elemSize = elemSize; // 元素字节大小
q->size = 0;
q->head = NULL; // 没有元素指向空
q->tail = NULL; // 没有元素指向空
}
return q;
}
销毁队列 destroy_queue
void destroy_queue(QE q)
{
assert(q != NULL);
clear_queue(q);
free(q);
}
清空队列 clear_queue
void clear_queue(QE q)
{
assert(q != NULL);
while (!empty_queue(q)) {
pop_queue(q, NULL);
}
/*
// 用for循环一个一个释放
struct _QNode *node, *next;
for (node = q->head; node != NULL; node = next) {
next = node->next;
free(node);
}
q->head = NULL;
q->tail = NULL;
q->size = 0;
*/
}
队列中元素个数 size_queue
size_t size_queue(QE q)
{
assert(q != NULL);
return q->size;
}
判断队列是否为空 empty_queue
bool empty_queue(QE q)
{
assert(q != NULL);
return q->size == 0; // q->head == NULL;
}
压入队尾 push_queue
int push_queue(QE q, const void *pElem)
{
assert(q != NULL && pElem != NULL);
struct _QNode *node = (struct _QNode*)malloc(_QNODESIZE + q->elemSize); // 结点大小+元素大小
if (node == NULL) {
return FAILURE;
}
node->next = NULL;
memcpy(node->elem, pElem, q->elemSize); // 拷贝元素
if (q->tail != NULL) {
q->tail->next = node; // 让node结点放到原来队尾结点的后面
} else { // 如果没有结点 那么node也得第一个结点
q->head = node; // 第一次压入
}
q->tail = node; // 队尾指针指向刚压入的元素结点
++q->size;
return SUCCESS;
}
从队头弹出 pop_queue
int pop_queue(QE q, void *pElem)
{
assert(q != NULL);
if (empty_queue(q)) {
return FAILURE;
}
struct _QNode *node = q->head;
if (pElem != NULL) { // 是否返回删除的元素
memcpy(pElem, node->elem, q->elemSize);
}
q->head = node->next;
if (node == q->tail) { // 只有一个结点 删除之后 head和tail都要为NULL
q->tail = NULL;
}
free(node);
--q->size;
return SUCCESS;
}
获取队头元素 front_queue
int front_queue(QE q, void *pElem)
{
assert(q != NULL && pElem != NULL);
if (empty_queue(q)) {
return FAILURE;
}
memcpy(pElem, q->head->elem, q->elemSize);
return SUCCESS;
}
获取队尾元素 back_queue
int back_queue(QE q, void *pElem)
{
assert(q != NULL && pElem != NULL);
if (empty_queue(q)) {
return FAILURE;
}
memcpy(pElem, q->tail->elem, q->elemSize);
return SUCCESS;
}
迭代 foreach_queue
void foreach_queue(QE q, void (*foreach)(const void*))
{
assert(q != NULL && foreach != NULL);
struct _QNode *node;
for (node = q->head; node != NULL; node = node->next) {
foreach(node->elem);
}
}