栈与队列的相互实现

在数据结构与算法中,栈和队列是两个重要的基础结构。它们的特性不同但却有趣地可以相互模拟实现,本文将通过C语言来探讨如何用栈实现队列,以及如何用队列实现栈

一、栈实现队列

用两个栈来实现队列的核心思想是:

  • 一个栈(输入栈)用于插入元素
  • 另一个栈(输出栈)用于移除元素

当需要从队列中取元素时,如果输出栈为空,则将输入栈的所有元素依次弹出并压入输出栈。

核心步骤

  1. 入队操作:将新元素压入输入栈。
  2. 出队操作:如果输出栈为空,则将输入栈的元素逐个弹出并压入输出栈;然后从输出栈弹出栈顶元素。

代码如下

​
#include <stdio.h>
#include <stdlib.h>

// 定义栈结构
typedef struct {
    int *data;
    int top;
    int capacity;
} Stack;

// 创建栈
Stack* createStack(int capacity) {
    Stack* stack = (Stack*)malloc(sizeof(Stack));
    stack->data = (int*)malloc(sizeof(int) * capacity);
    stack->top = -1;
    stack->capacity = capacity;
    return stack;
}

// 判断栈是否为空
int isEmpty(Stack* stack) {
    return stack->top == -1;
}

// 入栈
void push(Stack* stack, int x) {
    stack->data[++stack->top] = x;
}

// 出栈
int pop(Stack* stack) {
    return stack->data[stack->top--];
}

// 获取栈顶元素
int top(Stack* stack) {
    return stack->data[stack->top];
}

// 定义队列结构
typedef struct {
    Stack *inStack;
    Stack *outStack;
} Queue;

// 创建队列
Queue* createQueue(int capacity) {
    Queue* queue = (Queue*)malloc(sizeof(Queue));
    queue->inStack = createStack(capacity);
    queue->outStack = createStack(capacity);
    return queue;
}

// 入队操作
void enqueue(Queue* queue, int x) {
    push(queue->inStack, x);
}

// 出队操作
int dequeue(Queue* queue) {
    if (isEmpty(queue->outStack)) {
        while (!isEmpty(queue->inStack)) {
            push(queue->outStack, pop(queue->inStack));
        }
    }
    if (!isEmpty(queue->outStack)) {
        return pop(queue->outStack);
    }
    printf("Queue is empty!\n");
    return -1;
}

// 获取队头元素
int front(Queue* queue) {
    if (isEmpty(queue->outStack)) {
        while (!isEmpty(queue->inStack)) {
            push(queue->outStack, pop(queue->inStack));
        }
    }
    if (!isEmpty(queue->outStack)) {
        return top(queue->outStack);
    }
    printf("Queue is empty!\n");
    return -1;
}

// 测试
int main() {
    Queue* queue = createQueue(10);
    enqueue(queue, 1);
    enqueue(queue, 2);
    enqueue(queue, 3);

    printf("Dequeue: %d\n", dequeue(queue)); // 输出 1
    printf("Front: %d\n", front(queue));     // 输出 2

    enqueue(queue, 4);
    printf("Dequeue: %d\n", dequeue(queue)); // 输出 2
    printf("Dequeue: %d\n", dequeue(queue)); // 输出 3

    return 0;
}

​

二、队列实现栈

用两个队列来实现栈的核心思想是:

  • 始终保持一个队列为空,另一个队列存储数据;
  • 每次插入新元素时,通过两个队列的切换模拟栈的特性。

核心步骤

  1. 入栈操作:将元素加入非空队列。
  2. 出栈操作:将非空队列中除最后一个元素外的所有元素依次移入另一个空队列,然后删除最后一个元素。

代码如下

​
#include <stdio.h>
#include <stdlib.h>

// 定义队列结构
typedef struct {
    int *data;
    int front, rear;
    int size, capacity;
} Queue;

// 创建队列
Queue* createQueue(int capacity) {
    Queue* queue = (Queue*)malloc(sizeof(Queue));
    queue->data = (int*)malloc(sizeof(int) * capacity);
    queue->front = queue->rear = -1;
    queue->size = 0;
    queue->capacity = capacity;
    return queue;
}

// 判断队列是否为空
int isEmptyQueue(Queue* queue) {
    return queue->size == 0;
}

// 入队
void enqueueQueue(Queue* queue, int x) {
    queue->rear = (queue->rear + 1) % queue->capacity;
    queue->data[queue->rear] = x;
    queue->size++;
}

// 出队
int dequeueQueue(Queue* queue) {
    int item = queue->data[queue->front];
    queue->front = (queue->front + 1) % queue->capacity;
    queue->size--;
    return item;
}

// 定义栈结构
typedef struct {
    Queue *q1, *q2;
} Stack;

// 创建栈
Stack* createStackWithQueues(int capacity) {
    Stack* stack = (Stack*)malloc(sizeof(Stack));
    stack->q1 = createQueue(capacity);
    stack->q2 = createQueue(capacity);
    return stack;
}

// 入栈操作
void pushWithQueues(Stack* stack, int x) {
    enqueueQueue(stack->q1, x);
}

// 出栈操作
int popWithQueues(Stack* stack) {
    if (isEmptyQueue(stack->q1)) {
        printf("Stack is empty!\n");
        return -1;
    }
    while (stack->q1->size > 1) {
        enqueueQueue(stack->q2, dequeueQueue(stack->q1));
    }
    int item = dequeueQueue(stack->q1);
    Queue* temp = stack->q1;
    stack->q1 = stack->q2;
    stack->q2 = temp;
    return item;
}

// 测试
int main() {
    Stack* stack = createStackWithQueues(10);
    pushWithQueues(stack, 1);
    pushWithQueues(stack, 2);
    pushWithQueues(stack, 3);

    printf("Pop: %d\n", popWithQueues(stack)); // 输出 3
    printf("Pop: %d\n", popWithQueues(stack)); // 输出 2

    return 0;
}

​

总结一下

  • 栈实现队列依赖两个栈,一个负责输入,一个负责输出。
  • 队列实现栈依赖两个队列,借助队列的轮换来模拟栈的特性。
  • 代码实现中应注意边界情况,比如栈或队列为空的处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值