目录
题目
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push
、top
、pop
和 empty
)。
实现 MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。
注意:
- 你只能使用队列的标准操作 —— 也就是
push to back
、peek/pop from front
、size
和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
次push
、pop
、top
和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);
}