Leetcode 38

1 题目

225. 用队列实现栈

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppopempty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false

注意:

  • 你只能使用队列的标准操作 ------ 也就是 push to backpeek/pop from frontsizeis empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

复制代码
输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

提示:

  • 1 <= x <= 9
  • 最多调用100pushpoptopempty
  • 每次调用 poptop 都保证栈不为空

**进阶:**你能否仅用一个队列来实现栈。

2 代码实现

一个队列

cpp 复制代码
typedef struct tagListNode {
    struct tagListNode* next;
    int val;
} ListNode;

typedef struct {
    ListNode* top;
} MyStack;

MyStack* myStackCreate() {
    MyStack* stk = calloc(1, sizeof(MyStack));
    return stk;
}

void myStackPush(MyStack* obj, int x) {
    ListNode* node = malloc(sizeof(ListNode));
    node->val = x;
    node->next = obj->top;
    obj->top = node;
}

int myStackPop(MyStack* obj) {
    ListNode* node = obj->top;
    int val = node->val;
    obj->top = node->next;
    free(node);

    return val;
}

int myStackTop(MyStack* obj) {
    return obj->top->val;
}

bool myStackEmpty(MyStack* obj) {
    return (obj->top == NULL);
}

void myStackFree(MyStack* obj) {
    while (obj->top != NULL) {
        ListNode* node = obj->top;
        obj->top = obj->top->next;
        free(node);
    }
    free(obj);
}

二个队列

cpp 复制代码
#define LEN 20
typedef struct queue {
    int *data;
    int head;
    int rear;
    int size;
} Queue;

typedef struct {
    Queue *queue1, *queue2;
} MyStack;

Queue *initQueue(int k) {
    Queue *obj = (Queue *)malloc(sizeof(Queue));
    obj->data = (int *)malloc(k * sizeof(int));
    obj->head = -1;
    obj->rear = -1;
    obj->size = k;
    return obj;
}

void enQueue(Queue *obj, int e) {
    if (obj->head == -1) {
        obj->head = 0;
    }
    obj->rear = (obj->rear + 1) % obj->size;
    obj->data[obj->rear] = e;
}

int deQueue(Queue *obj) {
    int a = obj->data[obj->head];
    if (obj->head == obj->rear) {
        obj->rear = -1;
        obj->head = -1;
        return a;
    }
    obj->head = (obj->head + 1) % obj->size;
    return a;
}

int isEmpty(Queue *obj) {
    return obj->head == -1;
}

MyStack *myStackCreate() {
    MyStack *obj = (MyStack *)malloc(sizeof(MyStack));
    obj->queue1 = initQueue(LEN);
    obj->queue2 = initQueue(LEN);
    return obj;
}

void myStackPush(MyStack *obj, int x) {
    if (isEmpty(obj->queue1)) {
        enQueue(obj->queue2, x);
    } else {
        enQueue(obj->queue1, x);
    }
}

int myStackPop(MyStack *obj) {
    if (isEmpty(obj->queue1)) {
        while (obj->queue2->head != obj->queue2->rear) {
            enQueue(obj->queue1, deQueue(obj->queue2));
        }
        return deQueue(obj->queue2);
    }
    while (obj->queue1->head != obj->queue1->rear) {
        enQueue(obj->queue2, deQueue(obj->queue1));
    }
    return deQueue(obj->queue1);
}

int myStackTop(MyStack *obj) {
    if (isEmpty(obj->queue1)) {
        return obj->queue2->data[obj->queue2->rear];
    }
    return obj->queue1->data[obj->queue1->rear];
}

bool myStackEmpty(MyStack *obj) {
    if (obj->queue1->head == -1 && obj->queue2->head == -1) {
        return true;
    }
    return false;
}

void myStackFree(MyStack *obj) {
    free(obj->queue1->data);
    obj->queue1->data = NULL;
    free(obj->queue1);
    obj->queue1 = NULL;
    free(obj->queue2->data);
    obj->queue2->data = NULL;
    free(obj->queue2);
    obj->queue2 = NULL;
    free(obj);
    obj = NULL;
}

队列和栈学的很差,还没有什么思路,基本操作也不是很熟悉。

队列初始化

1. 函数定义

cpp 复制代码
Queue *initQueue(int k)
  • 函数名为 initQueue,参数 k 表示队列的最大容量(最多能存储的元素个数)。
  • 返回值类型是 Queue*,即返回一个指向初始化完成的队列结构体的指针。

2. 分配队列结构体空间

cpp 复制代码
Queue *obj = (Queue *)malloc(sizeof(Queue));
  • malloc(sizeof(Queue)):在堆内存中申请一块大小为 Queue 结构体大小的空间(用于存储队列的元信息,如头指针、尾指针等)。
  • (Queue *):将 malloc 返回的 void* 指针强制转换为 Queue* 类型,方便后续操作。
  • 最终将这块空间的地址赋值给指针 objobj 成为指向该队列结构体的指针。

3. 分配队列数据存储数组

cpp 复制代码
obj->data = (int *)malloc(k * sizeof(int));
  • obj->data:访问队列结构体中的 data 成员(这是一个 int* 指针,用于指向存储队列元素的数组)。
  • malloc(k * sizeof(int)):申请一块大小为 k * sizeof(int) 的空间(能存储 kint 类型的元素),作为队列的实际数据存储区。
  • (int *):将指针强制转换为 int* 类型,与 data 成员的类型匹配。

4. 初始化队列的元信息

cpp 复制代码
obj->head = -1;   // 头指针初始化为 -1,表示队列当前为空
obj->rear = -1;   // 尾指针初始化为 -1,表示队列当前为空
obj->size = k;    // 队列的最大容量设置为参数 k
  • head:队列的头指针,指向队头元素的位置(当队列为空时,通常设为 -1)。
  • rear:队列的尾指针,指向队尾元素的位置(当队列为空时,通常设为 -1)。
  • size:记录队列的最大容量(即 k),用于判断队列是否已满。

5. 返回初始化完成的队列

cpp 复制代码
return obj;
  • 将初始化好的队列结构体指针返回,调用者可以通过该指针操作这个队列(如入队、出队等)。

总结

initQueue 函数的作用是:

  1. 为队列结构体(存储元信息)分配内存;
  2. 为队列的实际数据存储区(数组)分配内存;
  3. 初始化头指针、尾指针(标记队列为空)和最大容量;
  4. 返回指向该队列的指针,供后续使用。

这个函数是队列操作的基础,后续的入队、出队等操作都需要基于这个初始化后的队列进行。

相关推荐
深邃-5 小时前
【数据结构与算法】-二叉树(2):实现顺序结构二叉树(堆的实现),向上调整算法,向下调整算法,堆排序,TOP-K问题
数据结构·算法·二叉树·排序算法·堆排序··top-k
We་ct8 小时前
LeetCode 5. 最长回文子串:DP + 中心扩展
前端·javascript·算法·leetcode·typescript
lilihuigz12 小时前
Tutor LMS 4.0 Beta版全新上线:以学习者为中心的移动优先学习体验
学习·在线教育·lms
William Dawson12 小时前
2026软考中级系统集成项目管理工程师备考笔记
笔记·系统集成项目管理工程师
王老师青少年编程12 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【哈夫曼贪心】:合并果子
c++·算法·贪心·csp·信奥赛·哈夫曼贪心·合并果子
叼烟扛炮13 小时前
C++第二讲:类和对象(上)
数据结构·c++·算法·类和对象·struct·实例化
天疆说13 小时前
【哈密顿力学】深入解读航天器交会最优控制中的Hamilton函数
人工智能·算法·机器学习
wuweijianlove14 小时前
关于算法设计中的代价函数优化与约束求解的技术7
算法
leoufung14 小时前
LeetCode 149: Max Points on a Line - 解题思路详解
算法·leetcode·职场和发展
样例过了就是过了14 小时前
LeetCode热题100 最长公共子序列
c++·算法·leetcode·动态规划