Leetcode-用队列实现栈(带图详解)

目录

题目

图解

代码


题目

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

实现 MyStack 类:

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

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsize 和 is 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
  • 最多调用100 次 pushpoptop 和 empty
  • 每次调用 pop 和 top 都保证栈不为空

图解

代码

代码注释中有解析哦

/*队列的结构*/
typedef int DataType;
// 创建队列结构
typedef struct QueueNode {
    struct QueueNode* Next;
    DataType val;
} QueueNode;
// 创建一个结构体来确定头/尾,可以避免使用二级指针,也可以用哨兵来避免使用二级指针
typedef struct Queue {
    QueueNode* head; // 头
    QueueNode* tail; // 尾
    int size;        // 计数
} Queue;
/*队列函数实现*/
// 初始化
void Q_Init(Queue* p) {
    // 断言
    assert(p);
    // 初始化结构体
    p->head = NULL;
    p->tail = NULL;
    p->size = 0;
}

// 入队
void Q_Push(Queue* p, DataType x) {
    // 开辟一个节点
    QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
    if (newnode == NULL) // 判断是否开辟成功
    {
        assert("malloc");
        return;
    }
    // 进行插入操作
    newnode->Next = NULL;
    newnode->val = x;
    if (p->tail == NULL) {
        p->head = p->tail = newnode;
    } else {
        p->tail->Next = newnode;
        p->tail = newnode; // 更新tail的指向
    }

    p->size++; // push一下节点个数++
}

// 出队
void Q_Pop(Queue* p) {
    assert(p);
    assert(p->size); // 节点不能为空

    // 进行出队
    if (p->head->Next == NULL) // 一个节点
    {
        free(p->head);
        p->head = p->tail = NULL;
    } else // 多个节点
    {
        QueueNode* tmp = p->head->Next; // 用临时变量存储head的下一个节点
        free(p->head);                  // 释放head的节点
        p->head = tmp;                  // 在更新head指向
    }
    p->size--; // pop一个节点个数--
}

// 节点数
int Q_Size(Queue* p) {
    assert(p);
    assert(p->size);
    return p->size;
}

// 获取头部
DataType Q_Front(Queue* p) {
    assert(p);
    assert(p->size);
    // 直接返回head的元素
    return p->head->val;
}
// 获取尾部
DataType Q_Back(Queue* p) {
    assert(p);
    assert(p->size);
    // 直接返回tail的元素
    return p->tail->val;
}

// 判断是否为空
bool Q_Empty(Queue* p) {
    assert(p);
    // return p->size == 0;
    return !p->size;
}
// 销毁
void Q_Destroy(Queue* p) {
    assert(p);
    QueueNode* cur = p->head;
    while (cur) {
        // 存储下一个位置
        QueueNode* tmp = cur->Next;
        free(cur);
        cur = tmp;
    }
    // 指针制空
    p->head = p->tail = NULL;
    p->size = 0;
}
// 简单来说就是用队列的结构来实现栈
typedef struct {
    // 创建两个队列
    Queue q1;
    Queue q2;
} MyStack;

// 初始化栈
MyStack* myStackCreate() {
    // 开辟
    MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
    // 对队列初始化
    Q_Init(&(obj->q1));
    Q_Init(&(obj->q2));
    // 返回初始化好的栈
    return obj;
}

void myStackPush(MyStack* obj, int x) {
    // 先判断在进行入栈
    if (!Q_Empty(&(obj->q1))) {
        Q_Push(&(obj->q1), x);
    } else {
        Q_Push(&(obj->q1), x);
    }
}

int myStackPop(MyStack* obj) {
    // 假设法
    Queue* Empty = &(obj->q1);
    Queue* No_Empty = &(obj->q2);
    if (!Q_Empty(&(obj->q1))) { // 如果q1不为NULL,就交换
        Empty = &(obj->q2);
        No_Empty = &(obj->q1);
    }
    // 找栈顶
    while (Q_Size(No_Empty) > 1) {
        // 先push,再pop
        Q_Push(Empty, Q_Front(No_Empty));
        Q_Pop(No_Empty);
    }
    int top = Q_Front(No_Empty); // 存储栈顶数据,需要返回
    Q_Pop(No_Empty);             // 出栈
    return top;
}

int myStackTop(MyStack* obj) {
    if (!Q_Empty(&(obj->q1))) {
        return Q_Back(&(obj->q1));
    } else {
        return Q_Back(&(obj->q2));
    }
}

bool myStackEmpty(MyStack* obj) {
    return Q_Empty(&(obj->q1)) && Q_Empty(&(obj->q2));
}

void myStackFree(MyStack* obj) {
    // 先释放队列结构
    Q_Destroy(&(obj->q1));
    Q_Destroy(&(obj->q2));
    // 再释放栈
    free(obj);
}

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

普通小青年.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值