题目
用栈实现队列
题目要求
示例
解答
方法一、
采用两个栈,将数据入栈出栈实现数据顺序的变化。
实现思路
我们定义一个栈为pushstack,当有元素要进入队列时,都将元素放入这个栈中。
然后定义一个popstack栈,当有元素出队列时,我们检查popstack栈是否为空,如果为空就将pushstack栈中的元素都加入到popstack栈中。此时popstack栈中元素出栈的顺序和出队列的顺序一致。
当再需要有元素入队时,直接将元素放入pushstack栈中即可,而有元素出队时就将popstack栈中的元素出栈,当popstack栈为空时,再将pushstack栈中的元素都加入popstack栈中。
时间复杂度和空间复杂度
时间复杂度:出队时最坏为O(N),入队时为O(1)
空间复杂度:O(N)
代码
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
//静态数组实现栈
//#define N 10
//typedef int STDataType;
//typedef struct Stack
//{
// STDataType a[N];
// int top;
//}ST;
//动态数组实现栈
typedef int STDataType;
typedef struct Stack
{
STDataType* data;
int top;
int capacity;
}ST;
//栈的初始化
void StackInit(ST* ps);
//检查栈空
bool StackEmpty(ST* ps);
//栈的销毁
void StackDestory(ST* ps);
//元素入栈
void StackPush(ST* ps, STDataType x);
//元素出栈
void StackPop(ST* ps);
//返回栈顶元素
STDataType StackTop(ST* ps);
void StackInit(ST* ps)
{
assert(ps);
ps->data = NULL;
ps->top = 0;
ps->capacity = 0;
}
bool StackEmpty(ST* ps)
{
assert(ps);
/*if (ps->top <= 0)
{
return true;
}
else
{
return false;
}*/
return ps->top == 0;
}
void StackDestory(ST* ps)
{
assert(ps);
//将动态数组申请的空间都释放。
free(ps->data);
ps->data = NULL;
ps->top = 0;
ps->capacity = 0;
}
void StackPush(ST* ps, STDataType x)
{
assert(ps);
//当栈的容量不够时
if (ps->top == ps->capacity)
{
//当动态数组的大小为0时,就申请4个空间;当动态数组大小不为0时,就说明栈满了,需要扩容。
int newCapacity = (ps->capacity == 0) ? 4 : (ps->capacity * 2);
//给动态数组申请空间,用来存放数据
STDataType* tmp = (STDataType*)realloc(ps->data, sizeof(STDataType) * newCapacity);
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->data = tmp;
ps->capacity = newCapacity;
}
//将数据存到数组的末尾,然后栈顶向后移。
ps->data[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)
{
assert(ps);
//出栈时要检查栈中有没有元素,有元素才可以出栈,没有元素就不可以出栈
assert(!StackEmpty(ps));
ps->top--;
}
STDataType StackTop(ST* ps)
{
assert(ps);
//出栈时要检查栈中有没有元素,有元素才可以出栈,没有元素就不可以出栈
assert(!StackEmpty(ps));
return ps->data[(ps->top)-1];
}
typedef struct {
//在该结构体中创建两个栈
ST popstack;
ST pushstack;
} MyQueue;
MyQueue* myQueueCreate() {
//该函数需要申请一个MyQueue*类型的结构体指针,并且将该结构体指针的返回,该结构体指针就代表一个队列
//然后通过操作该结构体指针指向的结构体中两个栈,来实现队列的一些操作。
MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue));
//将组成该队列的两个栈初始化。
StackInit(&(queue->popstack));
StackInit(&(queue->pushstack));
return queue;
}
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
StackPush(&(obj->pushstack),x);
}
int myQueuePop(MyQueue* obj) {
assert(obj);
//如果popstack栈为空,就将pushstack栈中的元素都入栈到popstack栈中。
if(StackEmpty(&(obj->popstack)))
{
while(!StackEmpty(&(obj->pushstack)))
{
//将pushstack栈中的元素都进入到popstack栈中
StackPush(&(obj->popstack),StackTop(&(obj->pushstack)));
//然后将pushstack栈中的元素都出栈。
StackPop(&(obj->pushstack));
}
}
//此时popstack栈中的元素出栈的顺序和队列中元素出队的顺序一致。
//此时popstack栈顶元素就是队列的队头元素
int top = StackTop(&(obj->popstack));
StackPop(&(obj->popstack));
return top;
}
int myQueuePeek(MyQueue* obj) {
assert(obj);
//如果popstack栈为空,就将pushstack栈中的元素都入栈到popstack栈中。
if(StackEmpty(&(obj->popstack)))
{
while(!StackEmpty(&(obj->pushstack)))
{
//将pushstack栈中的元素都进入到popstack栈中
StackPush(&(obj->popstack),StackTop(&(obj->pushstack)));
//然后将pushstack栈中的元素都出栈。
StackPop(&(obj->pushstack));
}
}
//此时popstack栈中的元素出栈的顺序和队列中元素出队的顺序一致。
return StackTop(&(obj->popstack));
}
bool myQueueEmpty(MyQueue* obj) {
assert(obj);
return StackEmpty(&(obj->popstack))&&StackEmpty(&(obj->pushstack));
}
void myQueueFree(MyQueue* obj) {
assert(obj);
StackDestory(&(obj->pushstack));
StackDestory(&(obj->popstack));
free(obj);
}