栈(Stack)和队列(Queue)是最基础、最常用的两种线性数据结构。
本篇博客将从概念、典型应用、实现细节,到性能分析,分步骤带你深入掌握各类实现方法。
┌───────┐ ← 栈顶 (top)
│ 30 │
│ 20 │
│ 10 │
└───────┘ ← 栈底
#define MAXSIZE 100
typedef struct {
int data[MAXSIZE];
int top; // 指向当前栈顶元素的下标,-1 表示空栈
} SeqStack;
// 初始化
void InitSeqStack(SeqStack *s) {
s->top = -1;
}
// 入栈
int PushSeq(SeqStack *s, int v) {
if (s->top >= MAXSIZE - 1) return 0; // 栈满
s->data[++s->top] = v;
return 1;
}
// 出栈
int PopSeq(SeqStack *s, int *v) {
if (s->top == -1) return 0; // 栈空
*v = s->data[s->top--];
return 1;
}
// 读栈顶
int TopSeq(SeqStack *s, int *v) {
if (s->top == -1) return 0;
*v = s->data[s->top];
return 1;
}
// 判空
int IsEmptySeq(SeqStack *s) {
return s->top == -1;
}
typedef struct StackNode {
int data;
struct StackNode *next;
} StackNode, *LinkStack;
// 初始化
void InitLinkStack(LinkStack *s) {
*s = NULL;
}
// 入栈:在链表头插入
void PushLink(LinkStack *s, int v) {
StackNode *node = (StackNode*)malloc(sizeof(StackNode));
node->data = v;
node->next = *s;
*s = node;
}
// 出栈:删除链表头
int PopLink(LinkStack *s, int *v) {
if (*s == NULL) return 0;
StackNode *tmp = *s;
*v = tmp->data;
*s = tmp->next;
free(tmp);
return 1;
}
// 取栈顶
int TopLink(LinkStack s, int *v) {
if (s == NULL) return 0;
*v = s->data;
return 1;
}
// 判空
int IsEmptyLink(LinkStack s) {
return s == NULL;
}
front → [10] [20] [30] ← rear
#define MAXQ 100
typedef struct {
int data[MAXQ];
int front; // 指向队头元素下标
int rear; // 指向队尾下一个位置
} SeqQueue;
// 初始化
void InitSeqQueue(SeqQueue *q) {
q->front = q->rear = 0;
}
// 入队
int EnQueue(SeqQueue *q, int v) {
if (q->rear == MAXQ) return 0; // 队满
q->data[q->rear++] = v;
return 1;
}
// 出队
int DeQueue(SeqQueue *q, int *v) {
if (q->front == q->rear) return 0; // 队空
*v = q->data[q->front++];
return 1;
}
// 取队头
int Front(SeqQueue *q, int *v) {
if (q->front == q->rear) return 0;
*v = q->data[q->front];
return 1;
}
// 判空
int IsEmptyQ(SeqQueue *q) {
return q->front == q->rear;
}
#define MAXQ 100
typedef struct {
int data[MAXQ];
int front; // 指向队头
int rear; // 指向队尾的下一个位置
} CircQueue;
// 初始化
void InitCircQueue(CircQueue *q) {
q->front = q->rear = 0;
}
// 判满:下一位置等于 front 则满
int IsFullCirc(CircQueue *q) {
return (q->rear + 1) % MAXQ == q->front;
}
// 入队
int EnCirc(CircQueue *q, int v) {
if (IsFullCirc(q)) return 0;
q->data[q->rear] = v;
q->rear = (q->rear + 1) % MAXQ;
return 1;
}
// 出队
int DeCirc(CircQueue *q, int *v) {
if (IsEmptyQ((SeqQueue*)q)) return 0; // front==rear
*v = q->data[q->front];
q->front = (q->front + 1) % MAXQ;
return 1;
}
typedef struct QNode {
int data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
QueuePtr front, rear;
} LinkQueue;
// 初始化
void InitLinkQueue(LinkQueue *q) {
q->front = q->rear = (QueuePtr)malloc(sizeof(QNode));
q->front->next = NULL;
}
// 入队:在链尾插入
void EnLink(LinkQueue *q, int v) {
QueuePtr node = (QueuePtr)malloc(sizeof(QNode));
node->data = v;
node->next = NULL;
q->rear->next = node;
q->rear = node;
}
// 出队:删除链头第一个节点
int DeLink(LinkQueue *q, int *v) {
if (q->front == q->rear) return 0; // 空队
QueuePtr tmp = q->front->next;
*v = tmp->data;
q->front->next = tmp->next;
if (q->rear == tmp) q->rear = q->front;
free(tmp);
return 1;
}
实现方式 | 空间复杂度 | 入/出操作 | 优点 | 适用场景 |
---|---|---|---|---|
顺序栈 | O(n) | O(1) | 简单、访问快 | 元素个数上限已知、对性能要求高 |
链式栈 | O(n) | O(1) | 动态、无栈满限制 | 元素个数动态、空间不预先分配 |
顺序队列 | O(n) | O(1) | 简单 | 入/出次数少、不关注循环复用 |
循环队列 | O(n) | O(1) | 空间高效、不需搬移元素 | 缓冲区、IO 队列、实时任务调度 |
链式队列 | O(n) | O(1) | 动态、无队满限制 | 元素动态、空闲链表场景 |