基本思想:一个栈实现队列的入,一个栈实现队列的出
假设先将元素都压入st1,如果将st1中的元素逐个弹出并压入st2,则元素在st2中的顺序正好和原来在st1中的顺序相反,也就是st2中的栈顶元素就是队列中先入的元素,然后弹出st2的栈顶元素,就实现了队列的“先入先出”的特点
当st2不为空时,在st2中的栈顶元素是最先进如队列的元素,可以弹出;当st2为空时,需将st1中的元素全部弹出并压入st2.
首先必须有一个实现栈的各种操作的文件
typedef int TYDataType;
typedef struct Skack
{
TYDataType* a;
int top;
int capacity;
}ST;
//初始化栈
void StackInit(ST* ps);
//销毁栈
void StackDestory(ST* ps);
//从栈顶插入元素
//入栈
void StackPush(ST* ps, TYDataType X);
//出栈
void StackPop(ST* ps);
//查找栈顶元素
TYDataType StackTop(ST* ps);
//求栈中的元素个数
int StackSize(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);
再将其一一实现
void StackInit(ST* ps)
{
assert(ps);
ps->a = (TYDataType*)malloc(sizeof(TYDataType) * 4);
if (ps->a == NULL)
{
printf("malloc fail\n");
exit(-1);
}
ps->capacity = 4;
//若top取0,则top指向栈顶元素的下一个
//若top取-1,则top指向栈顶元素
ps->top = 0;
}
void StackDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = 0;
ps->top = 0;
}
//从栈顶插入元素
//入栈
void StackPush(ST* ps, TYDataType X)
{
assert(ps);
//如果满了,则需要扩容
if (ps->top == ps->capacity)
{
TYDataType* tmp = (TYDataType*)realloc(ps->a, sizeof(TYDataType) * (ps->capacity * 2));
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
else
{
ps->a = tmp;
ps->capacity *= 2;
}
}
ps->a[ps->top] = X;
ps->top++;
}
//出栈
void StackPop(ST* ps)
{
assert(ps);
//如果栈空了,调用Pop,直接终止程序报错
assert(ps->top > 0);
ps->top--;
}
//查找栈顶元素
TYDataType StackTop(ST* ps)
{
assert(ps);
//如果栈空了,调用Top,直接终止程序报错
assert(ps->top > 0);
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;
}
先创建出两个栈st1和st2,并进行初始化
//创建两个栈
typedef struct {
ST st1;
ST st2;
} MyQueue;
//将其初始化
MyQueue* myQueueCreate() {
MyQueue* ps = (MyQueue*)malloc(sizeof(MyQueue));
if (ps == NULL)
{
printf("malloc fail\n");
exit(-1);
}
StackInit(&ps->st1);
StackInit(&ps->st2);
return ps;
}
入队:先将数字1,2插入到st1当中
//入队
void myQueuePush(MyQueue* obj, int x) {
StackPush(&obj->st1,x);
}
出队:出栈时分为两种情况:(一种st2中没有数据,另一种则是st2中有数据)
1.st2为空,则需要将st1中的数据从栈顶依次取出放入st2中。然后再将st2栈顶的元素删除并返回(根据题目要求)。
2.st2不为空,则只需要返回其栈顶的元素即可。
特别要注意当st2中没有元素时,才能将st1中的元素放入st2中。不然就不满足队列先进先出的性质。不然会出现这种情况
//出队
int myQueuePop(MyQueue* obj) {
if (StackEmpty(&obj->st2))
{
while(StackSize(&obj->st1) > 0)
{
StackPush(&obj->st2,StackTop(&obj->st1));
StackPop(&obj->st1);
}
}
int top = StackTop(&obj->st2);
StackPop(&obj->st2);
return top;
}
返回队开头的元素:此时和出栈一样分为两种情况:(一种st2中没有数据,另一种则是st2中有数据)
1.st2为空,若为空则将其st1中的元素先依次从栈顶取出放入st2中,再将st2栈顶的元素返回
2.st2不为空,直接返回st2栈顶元素
//返回队开头的元素
int myQueuePeek(MyQueue* obj) {
if (StackEmpty(&obj->st2))
{
while(StackSize(&obj->st1) > 0)
{
StackPush(&obj->st2,StackTop(&obj->st1));
StackPop(&obj->st1);
}
}
return StackTop(&obj->st2);
}
判断队列是否为空:只要st1和st2都为空时,队列则为空
//判断队列是否为空
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(&obj->st1) && StackEmpty(&obj->st2);
}
销毁队列:先将创建出来的st1和st2free,再将整个队列free
//销毁队列
void myQueueFree(MyQueue* obj) {
StackDestory(&obj->st1);
StackDestory(&obj->st2);
free(obj);
}