目录
- 题目
- 题目分析
- 代码
- 栈的实现
- 结构体。
- 栈的初始化
- 栈的销毁
- 入栈
- 删除
- 查找顶部数据
- 判空
- 答案
- 结构体
- 初始化
- 插入数据
- 删除数据
- 获取队列开头元素
- 判空
- 销毁栈
题目
题目分析
链接: 题目
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
根据题目,我们可以知道,我们需要用两个栈来实现队列,栈的出入规则是后进先出,而队列的出入规则是先进先出。
如果我们现在又两个栈,pushpst
和popst
,先在pushst中入4个数据(4,3,2,1)。
如果我们要出数据的话,我们根据队列的出入原则,应该出数据1,所以我们可以把pushst里面的数据全部倒入到popst中,那么popst中的数据为(1,2,3,4).
如图:
如果需要出数据的话,直接按照顺序出就可以了。
那么,问题来了,我们要入数据,需要在哪个栈里面入?
答案是pushst
.如果我们要入数据(5,6).
pushst拿来入数据,popst拿来出数据,刚好可以满足队列的需求。先出四个数据。
想再出数据时,已经没有数据了,我们需要从pushst里再次倒入数据(5,6),
再依此类推…
代码
栈的实现
我们实现栈使用的是数组。
结构体。
先创建一个结构体
typedef int STDataType;
typedef struct stack
{
STDataType* a;
int top;//栈当前大小
int capacity;//栈的大小
}ST;
栈的初始化
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->capacity = 0;
pst->top = 0;
}
栈的销毁
void STDestory(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = pst->top = 0;
}
入栈
void Push(ST* pst, STDataType x)
{
assert(pst);
if (pst->top == pst->capacity)//如果栈的空间不够了,我们需要扩容。
{
int newnode = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newnode);
if (tmp == NULL) {
perror("realloc:fail");
}
pst->a = tmp;
pst->capacity = newnode;
}
pst->a[pst->top++] = x;
}
删除
void Pop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
pst->top--;//只需要顶部删除即可
}
查找顶部数据
STDataType Top(ST* pst)
{
return pst->a[pst->top-1];
}
判空
bool STEmpty(ST* pst)
{
assert(pst);
return pst->top == 0;
}
答案
我们需要先创建两个栈的结构体
结构体
typedef struct {
ST pushst;
ST popst;
} MyQueue;
初始化
MyQueue* myQueueCreate() {
MyQueue * obj = (MyQueue*)malloc(sizeof(MyQueue));
STInit(&obj->pushst);//对每一个队列进行初始化
STInit(&obj->popst);
return obj;
}
插入数据
void myQueuePush(MyQueue* obj, int x) {
Push(&obj->pushst,x);//只需要往pushst里面插入就可以了
}
删除数据
先对popst判空,如果为空,我们需要倒入数据后,再删除数据。
int myQueuePop(MyQueue* obj) {
if(STEmpty(&obj->popst))
{
while(!STEmpty(&obj->pushst))
{
Push(&obj->popst,Top(&obj->pushst));
Pop(&obj->pushst);//倒入一个,记得删除一个
}
}
int top = Top(&obj->popst);//获取顶部苏数据
Pop(&obj->popst);//删除顶部数据
return top;
}
获取队列开头元素
跟myQueuePop(MyQueue* obj)函数类似
int myQueuePeek(MyQueue* obj) {
if(STEmpty(&obj->popst))
{
while(!STEmpty(&obj->pushst))
{
Push(&obj->popst,Top(&obj->pushst));
Pop(&obj->pushst);
}
}
return Top(&obj->popst);
}
判空
两个栈为空,队列才为空。
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->popst) && STEmpty(&obj->pushst);
}
销毁栈
先要对连个队列进行销毁,再对两个栈的结构体销毁。
void myQueueFree(MyQueue* obj) {
STDestory(&obj->popst);
STDestory(&obj->pushst);
free(obj);
}