232.用栈实现队列
题目链接/文章讲解/视频讲解:代码随想录
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(
push
、pop
、peek
、empty
):实现
MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
说明:
- 你 只能 使用标准的栈操作 —— 也就是只有
push to top
,peek/pop from top
,size
, 和is empty
操作是合法的。- 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
分析及思路
队列是先进先出,我们使用一个out只进行出,in只进行进。
初始化时,输出顶指针和输入顶指针初始化设置为-1,进栈时先加顶指针在赋值,出栈时先赋值在减顶指针。出栈时我们只在out出栈。初始化时队列为空,即OutTop和InTop = -1,即它两个都为-1时为空。释放空间时我们直接都设置为-1即可元素不用删除进行覆盖即可。
获取顶指针时,若out有元素,则顶指针所指即为队头。否则in[0]为队头元素。
代码及注释
// 定义一个名为MyQueue的结构体
typedef struct MyQueue{
int OutTop; // 输出栈顶索引
int InTop; // 输入栈顶索引
int Out[100]; // 输出栈
int In[100]; // 输入栈
} MyQueue;
// 创建一个MyQueue结构体的指针
MyQueue* myQueueCreate() {
MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue)); // 分配内存空间
queue->OutTop = -1; // 初始化输出栈顶索引为-1
queue->InTop = -1; // 初始化输入栈顶索引为-1
return queue; // 返回指针
}
// 将元素x推入队列
void myQueuePush(MyQueue* obj, int x) {
obj->InTop++; // 输入栈顶索引加1
obj->In[obj->InTop] = x; // 将元素x放入输入栈
}
// 弹出队列的第一个元素
int myQueuePop(MyQueue* obj) {
int temp; // 临时变量
if( obj->OutTop == -1 ){ // 如果输出栈为空
while( obj->InTop > -1 ){ // 循环直到输入栈为空
obj->OutTop++; // 输出栈顶索引加1
obj->Out[obj->OutTop] = obj->In[obj->InTop]; // 将输入栈的元素弹出并放入输出栈
obj->InTop--; // 输入栈顶索引减1
}
}
temp = obj->Out[obj->OutTop]; // 将输出栈的顶部元素赋给临时变量
obj->OutTop--; // 输出栈顶索引减1
return temp; // 返回临时变量
}
// 返回队列的第一个元素
int myQueuePeek(MyQueue* obj) {
if(obj->OutTop > -1) // 如果输出栈不为空
return obj->Out[obj->OutTop]; // 返回输出栈的顶部元素
return obj->In[0]; // 如果输出栈为空,则返回输入栈的第一个元素
}
// 检查队列是否为空
bool myQueueEmpty(MyQueue* obj) {
if( (obj->OutTop==-1) && (obj->InTop==-1) ){ // 如果输出栈和输入栈都为空
return true; // 返回true
}
return false; // 否则返回false
}
// 释放队列的内存空间
void myQueueFree(MyQueue* obj) {
obj->InTop = -1; // 输入栈顶索引重置为-1
obj->OutTop = -1; // 输出栈顶索引重置为-1
}
225. 用队列实现栈
题目链接/文章讲解/视频讲解:代码随想录
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(
push
、top
、pop
和empty
)。实现
MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。
两个队列实现
分析及思路
一个进行输入和输出,另一个起到缓冲的作用。
代码及注释
#define MAX_SIZE 100 // 定义栈的最大容量为100
typedef struct { // 定义结构体 MyStack
int front1, rear1, front2, rear2; // 定义四个整型变量front1, rear1, front2, rear2
int data1[MAX_SIZE], data2[MAX_SIZE]; // 定义两个整型数组data1和data2,大小为MAX_SIZE
} MyStack; // 结构体别名为 MyStack
MyStack* myStackCreate() { // 创建一个新的 MyStack 结构体
MyStack* temp = (MyStack*)malloc(sizeof(MyStack)); // 分配内存给temp,大小为MyStack结构体的大小
temp->front1 = 0; // 将temp的front1成员赋值为0
temp->front2 = 0; // 将temp的front2成员赋值为0
temp->rear1 = 0; // 将temp的rear1成员赋值为0
temp->rear2 = 0; // 将temp的rear2成员赋值为0
return temp; // 返回指向新分配的MyStack结构体的指针
}
void myStackPush(MyStack* obj, int x) { // 向栈中压入一个元素
if (obj->front1 == (obj->rear1 + 1) % MAX_SIZE) // 如果front1等于(rear1+1)%MAX_SIZE
return; // 退出函数
obj->data1[obj->rear1] = x; // 将x存入data1数组的rear1位置
obj->rear1 = (obj->rear1 + 1) % MAX_SIZE; // 更新rear1的位置
}
int myStackPop(MyStack* obj) { // 从栈中弹出一个元素
while ((obj->front1 + 1) % MAX_SIZE != obj->rear1) { // 当front1+1对MAX_SIZE取余不等于rear1时循环
obj->data2[obj->rear2] = obj->data1[obj->front1]; // 将data1数组的front1位置的元素存入data2数组的rear2位置
obj->rear2 = (obj->rear2 + 1) % MAX_SIZE; // 更新rear2的位置
obj->front1 = (obj->front1 + 1) % MAX_SIZE; // 更新front1的位置
}
int temp = obj->data1[obj->front1]; // 将data1数组的front1位置的元素存入temp
obj->front1 = (obj->front1 + 1) % MAX_SIZE; // 更新front1的位置
while (obj->front2 != obj->rear2) { // 当front2不等于rear2时循环
obj->data1[obj->rear1] = obj->data2[obj->front2]; // 将data2数组的front2位置的元素存入data1数组的rear1位置
obj->rear1 = (obj->rear1 + 1) % MAX_SIZE; // 更新rear1的位置
obj->front2 = (obj->front2 + 1) % MAX_SIZE; // 更新front2的位置
}
return temp; // 返回temp
}
int myStackTop(MyStack* obj) { // 返回栈顶元素的值
int temp = myStackPop(obj); // 调用myStackPop函数,并将返回值存入temp
myStackPush(obj, temp); // 调用myStackPush函数,将temp压入栈中
return temp; // 返回temp
}
void myStackFree(MyStack* obj) { // 释放栈
obj->front1 = obj->rear1; // 将front1赋值为rear1
obj->front2 = obj->rear2; // 将front2赋值为rear2
}
bool myStackEmpty(MyStack* obj) { // 判断栈是否为空
if (obj->front1 == obj->rear1) // 如果front1等于rear1
return true; // 返回true
return false; // 否则返回false
}
一个队列实现
由于另一个队列只实现缓冲的作用,我们可以直接把取出的元素直接放到原队列中。
代码及注释
```c
#define MAX_SIZE 100 // 定义栈的最大容量为100
typedef struct { // 定义结构体 MyStack
int front1, rear1; // 定义两个整型变量 front1 和 rear1
int data1[MAX_SIZE]; // 定义一个整型数组 data1,大小为 MAX_SIZE
} MyStack; // 结构体别名为 MyStack
MyStack* myStackCreate() { // 创建一个新的 MyStack 结构体
MyStack* temp = (MyStack*)malloc(sizeof(MyStack)); // 分配内存给 temp,大小为 MyStack 结构体的大小
temp->front1 = 0; // 将 temp 的 front1 成员赋值为 0
temp->rear1 = 0; // 将 temp 的 rear1 成员赋值为 0
return temp; // 返回指向新分配的 MyStack 结构体的指针
}
void myStackPush(MyStack* obj, int x) { // 向栈中压入一个元素
if (obj->front1 == (obj->rear1 + 1) % MAX_SIZE) // 如果 front1 等于 (rear1+1)%MAX_SIZE
return; // 退出函数
obj->data1[obj->rear1] = x; // 将 x 存入 data1 数组的 rear1 位置
obj->rear1 = (obj->rear1 + 1) % MAX_SIZE; // 更新 rear1 的位置
}
int myStackPop(MyStack* obj) { // 从栈中弹出一个元素
int temp = obj->rear1; // 将 rear1 的值存入 temp
while ((obj->front1 + 1) % MAX_SIZE != temp) { // 当 (front1+1)%MAX_SIZE 不等于 temp 时循环
obj->data1[obj->rear1] = obj->data1[obj->front1]; // 将 data1 数组的 front1 位置的元素存入 rear1 位置
obj->rear1 = (obj->rear1 + 1) % MAX_SIZE; // 更新 rear1 的位置
obj->front1 = (obj->front1 + 1) % MAX_SIZE; // 更新 front1 的位置
}
int temp1 = obj->data1[obj->front1]; // 将 data1 数组的 front1 位置的元素存入 temp1
obj->front1 = (obj->front1 + 1) % MAX_SIZE; // 更新 front1 的位置
return temp1; // 返回 temp1
}
int myStackTop(MyStack* obj) { // 返回栈顶元素的值
int temp = myStackPop(obj); // 调用 myStackPop 函数,并将返回值存入 temp
myStackPush(obj, temp); // 调用 myStackPush 函数,将 temp 压入栈中
return temp; // 返回 temp
}
void myStackFree(MyStack* obj) { // 释放栈
obj->front1 = obj->rear1; // 将 front1 赋值为 rear1
}
bool myStackEmpty(MyStack* obj) { // 判断栈是否为空
if (obj->front1 == obj->rear1) // 如果 front1 等于 rear1
return true; // 返回 true
return false; // 否则返回 false
}
```