一:实现栈
二:用栈实现队列
一:实现栈
简单过一下栈的概念:
栈是一种特殊的线性表,只允许在固定的一端进行插入删除元素操作,进行数据插入,删除的一端叫做栈顶,另一端叫做栈底。
然后他是用顺序表实现的,因为尾上插入数据时间复杂度小,具有先进后出特性
而队列具有先进先出特征。栈,队列看着没啥关系,如何用栈实现队列呢?
总体思路:开出两个栈,先将数据按照次序放入其中一个栈中,而另外一个栈什么都不放,处于置空状态。将放了数据的栈按照先进后出依次放入空栈,然后再出栈,这时刚好满足先进先出条件
总体思路图如下
有队列,得有空间放队列,先创建队列
用malloc创建空间来放队列,创建两个栈,一个为pushST,一个是popST,
我们要复制粘贴我曾经写过的实现栈的代码
#include<stdbool.h>
//定义栈的结构
typedef int STDataType;
typedef struct Stack
{
STDataType* arr;
int capacity;
int top;
}ST;
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
bool StackEmpty(ST* ps);
void STInit(ST* ps)
{
assert(ps);
ps->arr = NULL;
ps->capacity = ps->top = 0;
}
void STDestroy(ST* ps)
{
assert(ps);
/*if (ps->arr)
free(ps->arr);
ps->arr = NULL;
ps->capacity = ps->top = 0;*/
if (ps->arr != NULL)
{
free(ps->arr);
ps->arr =NULL;
ps->capacity = ps->top = 0;
}
else
{
ps->top;
}
}
void StackPush(ST* ps, STDataType x)
{
assert(ps);
//判断空间是否足够
if (ps->capacity == ps->top)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType* )realloc(ps->arr, newCapacity * sizeof(STDataType));
//空间申请失败
if (tmp == NULL)
{
printf("ralloc fail");
exit(-1);
}
ps->arr=tmp;
ps->capacity= newCapacity;
}
//空间足够
ps->arr[ps->top++] = x;
}
//栈取数据
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
--ps->top;
}
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
STDataType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->arr[ps->top - 1];
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
有了栈,有了总体思路,那就可以开始干了。
把数据放入pushST,popST是置空状态,对他不做任何处理的
//往pushST插入数据
void myQueuePush(MyQueue* obj, int x) {
StackPush(&obj->pushST,x);
}
然后是从pushST从上开始出数据放到空栈popST,一直到出完全部数据
//1.检查popST是否为空
// 1)不为空,直接出
// 2)为空,pushST导入到popST,再出数据
int myQueuePop(MyQueue* obj) {
if(StackEmpty(&obj->popST))
{
//导数据
while(!StackEmpty(&obj->pushST))
{
StackPush(&obj->popST,StackTop(&obj->pushST));
StackPop(&obj->pushST);
}
}
//出数据
int top= StackTop(&obj->popST);//StackTop(ST* ps)
StackPop(&obj->popST);
return top;
}
接着把栈popST出栈,出栈顺序为1,2,3,这会儿栈已经实现了队列
题中还有要求哦
返回队列开头的元素,首先要实现队列嘛,我们已经实现,拿来用就行,而出栈的元素即为开头元素,直接返回出栈的元素不就可以
//取队头
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);
}
、如果队列为空,意味着两个栈为空,直接返回这两个栈结构
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}
最后要销毁这个队列
void myQueueFree(MyQueue* obj) {
STDestroy(&obj->pushST);
STDestroy(&obj->popST);
free(obj);
obj = NULL;
}