特性:后进先出(LIFO)
push
: 元素入栈
pop
: 栈顶元素出栈
peek
: 查看栈顶元素
特性:先进先出(FIFO)
enqueue
: 元素入队
dequeue
: 队首元素出队
front
: 查看队首元素
栈的LIFO特性与队列的FIFO需求存在根本性冲突,单个栈无法直接实现队列。
使用两个栈协同工作:
// 入队操作
void enQueue(Queue* queue, int value) {
push(&queue->input_stack, value);
}
// 出队操作
int deQueue(Queue* queue) {
if (isStackEmpty(&queue->output_stack)) {
// 当输出栈为空时,转移全部元素
while (!isStackEmpty(&queue->input_stack)) {
push(&queue->output_stack, pop(&queue->input_stack));
}
}
return pop(&queue->output_stack);
}
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
// 栈结构体
typedef struct {
int data[MAX_SIZE];
int top;
} Stack;
// 初始化栈
void initStack(Stack* s) {
s->top = -1;
}
// 判断栈空
int isStackEmpty(Stack* s) {
return s->top == -1;
}
// 判断栈满
int isStackFull(Stack* s) {
return s->top == MAX_SIZE - 1;
}
// 入栈
void push(Stack* s, int val) {
if (isStackFull(s)) {
printf("Stack Overflow\n");
exit(1);
}
s->data[++s->top] = val;
}
// 出栈
int pop(Stack* s) {
if (isStackEmpty(s)) {
printf("Stack Underflow\n");
exit(1);
}
return s->data[s->top--];
}
// 队列结构体(包含两个栈)
typedef struct {
Stack input_stack;
Stack output_stack;
} Queue;
// 初始化队列
void initQueue(Queue* q) {
initStack(&q->input_stack);
initStack(&q->output_stack);
}
// 入队操作
void enQueue(Queue* q, int val) {
if (isStackFull(&q->input_stack)) {
printf("Queue is Full\n");
return;
}
push(&q->input_stack, val);
}
// 出队操作
int deQueue(Queue* q) {
if (isStackEmpty(&q->output_stack)) {
if (isStackEmpty(&q->input_stack)) {
printf("Queue is Empty\n");
exit(1);
}
// 转移全部元素
while (!isStackEmpty(&q->input_stack)) {
push(&q->output_stack, pop(&q->input_stack));
}
}
return pop(&q->output_stack);
}
// 获取队首元素
int queueFront(Queue* q) {
if (isStackEmpty(&q->output_stack)) {
while (!isStackEmpty(&q->input_stack)) {
push(&q->output_stack, pop(&q->input_stack));
}
}
return q->output_stack.data[q->output_stack.top];
}
// 判断队列是否为空
int isQueueEmpty(Queue* q) {
return isStackEmpty(&q->input_stack) && isStackEmpty(&q->output_stack);
}
操作 | 时间复杂度 | 摊还复杂度 |
---|---|---|
入队 | O(1) | O(1) |
出队 | O(n) | O(1) |
摊还分析:每个元素最多经历两次入栈和两次出栈操作,总体时间复杂度保持O(1)
O(n),需要维护两个栈的存储空间
int main() {
Queue q;
initQueue(&q);
// 测试用例
enQueue(&q, 1);
enQueue(&q, 2);
enQueue(&q, 3);
printf("Dequeue: %d\n", deQueue(&q)); // 应输出1
printf("Front: %d\n", queueFront(&q)); // 应输出2
enQueue(&q, 4);
printf("Dequeue: %d\n", deQueue(&q)); // 应输出2
printf("Dequeue: %d\n", deQueue(&q)); // 应输出3
printf("Dequeue: %d\n", deQueue(&q)); // 应输出4
return 0;
}
如何用队列实现栈?(LeetCode 225题)
通过这种双栈结构的设计,我们成功突破了数据结构固有特性的限制,实现了不同数据结构间的特性转换。这种设计思路体现了计算机科学中"用简单组件构建复杂系统"的典型方法论,建议读者可以尝试实现其他数据结构间的相互模拟来加深理解。