题一:用栈实现队列
1.链接
2.思路
这里要求用栈的特性和结构来去实现队列
栈是后进先出,栈的入栈和出栈都是从栈顶开始的
3.代码及解释
3.1创建栈的结构
若队栈不太请楚的,请看我之前的文章栈和队列详解-CSDN博客
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
//这是栈
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
void StackInit(ST* ps);
void StackDestroy(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
STDataType StackTop(ST* ps);
int StackSize(ST* ps);
bool StackEmpty(ST* ps);
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
void StackPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = realloc(ps->a, sizeof(STDataTyp)*newCapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
ps->a[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->a[ps->top - 1];
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
3.2创建队列的结构
这里会有两个栈
一个栈用来存数据,另一个用来删除数据
此时栈一 ,有五个数据,现在要实现将1给删除掉,由于栈要求要后进先出,那么如果我们将数据 全挪到栈2中,因为栈的特点,故我们先将5给挪到栈2的栈底,然后依次挪,挪到最后的时候,1就在栈2的栈顶,此时可以直接调用栈的函数进行删除,可以将栈2中的数据全删除掉。
故将栈2命名为 popST
要插入数据时,不能插入到栈2中,如果插入到栈2,那么由于栈的性质,会插到数据1的前面,那么就打乱了顺序,故我们要插,只能插到栈1中,故将栈一命名为pushST
typedef struct {
ST pushST;
ST popST;
} MyQueue;
3.3初始化队列
由于队列是由两个栈来构建的,则初始化队列,就相当于先创建好一个MyQueue,然后在初始化两个栈
MyQueue* myQueueCreate()
{
MyQueue* qe=(MyQueue*)malloc(sizeof(MyQueue));
StackInit(&qe->pushST);
StackInit(&qe->popST);
return qe;
}
3.4实现队列数据的插入
直接往栈pushST里插入数据,实现这一步操作,只需要调用函数StackPush就行
void myQueuePush(MyQueue* obj, int x) {
StackPush(&obj->pushST,x);
}
3.5实现返回队列开头的元素
先判断popST是否为空,如果为空,那么就将pushST的数据全移到popST中去,然后在调用函数StackTop来返回队列开头的元素。
int myQueuePeek(MyQueue* obj) {
if(StackEmpty(&obj->popST))
{
while(!StackEmpty(&obj->pushST))
{
StackPush(&obj->popST,StackTop(&obj->pushST));
StackPop(&obj->pushST);
}
}
return StackTop(&obj->popST);
}
3.6实现从队列的开头移除并返回元素
int myQueuePop(MyQueue* obj)
{
int front=myQueuePeek(obj);//调用函数,来将数据有顺序的导入到popST中
StackPop(&obj->popST);//删除队列的第一个元素
return front;//返回队列里第一个数据
}
3.7判断队列是否为空
由于队列是由两个栈来构建的,判断是否为空,即判断两个栈是否为空
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(&obj->pushST)&&StackEmpty(&obj->popST);
}
3.8释放队列
由于队列是由两个栈来构建的,销毁队列,即是销毁两个栈
void myQueueFree(MyQueue* obj) {
StackDestroy(&obj->popST);
StackDestroy(&obj->pushST);
free(obj);
}