1 题目
请你仅使用两个队列实现一个后入先出(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都保证栈不为空
**进阶:**你能否仅用一个队列来实现栈。
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*类型,方便后续操作。- 最终将这块空间的地址赋值给指针
obj,obj成为指向该队列结构体的指针。
3. 分配队列数据存储数组
cpp
obj->data = (int *)malloc(k * sizeof(int));
obj->data:访问队列结构体中的data成员(这是一个int*指针,用于指向存储队列元素的数组)。malloc(k * sizeof(int)):申请一块大小为k * sizeof(int)的空间(能存储k个int类型的元素),作为队列的实际数据存储区。(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 函数的作用是:
- 为队列结构体(存储元信息)分配内存;
- 为队列的实际数据存储区(数组)分配内存;
- 初始化头指针、尾指针(标记队列为空)和最大容量;
- 返回指向该队列的指针,供后续使用。
这个函数是队列操作的基础,后续的入队、出队等操作都需要基于这个初始化后的队列进行。