我们使用的是单向、不循环、不带头的链表实现,通过< 头删 + 尾插 >的方式完成,因为其时间复杂度都是O(1)
,便捷高效。
顺序表也可以完成队列的实现,不过其效率相对于单链表来说就不太理想了,时间复杂度为O(N)
,因为存在遍历操作。
定义
#pragma once //头文件只会被包含一次
//链表结点结构体定义
typedef struct Node {
int value;
struct Node *next;
} Node;
//队列结构体定义
typedef struct Queue {
Node *head; // 链表的第一个结点,队首元素
Node *last; // 链表的最后一个结点,队尾元素
} Queue;
初始化 ----Init
void QInit(Queue *q) {
q->head = NULL;
q->last = NULL:
}
入队 ----Push
void QPush(Queue *q, int v) {
Node *node = (Node*)malloc(sizeof(Node));
node->value = v;
node->next = NULL;
//如果链队为空,则说明新结点既是队首结点又是队尾结点,入队后整个队列只有一个元素
if (q->head == NULL) {
q->head = node;
q->last = node;
}
//如果链队非空,则依次修改队尾结点的指针域和队尾指针,更新队尾指针指向新的队尾结点
else {
q->last->next = node;
q->last = node;
}
}
出队 ----Pop
void QPop(Queue *q) {
assert(q != NULL);
assert(q->head != NULL);
//头删首结点
Node *head = q->head;
q->head = q->head->next;
free(head);
//若删除后链队为空,则需要同时使队尾指针为空
if (q->head == NULL) {
q->last = NULL;
}
}
获取队首元素 ----Front
int QFront(Queue *q) {
//空队列情况
if(q->head == NULL){
return NULL;
}
return q->head->value;
}
获取队中元素个数 ----Size
int QSize(Queue *q) {
int size = 0;
for (Node *c = q->head; c != NULL; c = c->next) {
size++;
}
return size;
}
判定是否为空队 ----Empty
int QEmpty(Queue *q) {
return q->head == NULL ? 1 : 0;
}