题目:
思路:
- 了解用栈实现队列的原理:先把目标队列(例1、2、3、4、5)按顺序压入stackin栈中,栈实行先入后出准则,此时stackin栈全部pop的结果将反向(5、4、3、2、1),为了正向输出,需要一个辅助栈stackout,压入stackin栈的元素,后再次反向(1、2、3、4、5),则输出完成
- step①:利用数据结构声明两个栈(注意与链表不同的是,栈可看做数组与链表的结合体)
typedef struct {
int InTop;
int OutTop;
// 创建两个栈的栈顶指针
int stackIn[100];
int stackOut[100];
// 设置两个栈的大小,题目提示不大于100
} MyQueue;
// 创建栈
MyQueue* myQueueCreate() {
//首先申请一个队列的空间
MyQueue *obj=(MyQueue*)malloc(sizeof(MyQueue));
// 初始化
obj->InTop=0;
obj->OutTop=0;
return obj;
}
- step②:实现push(既使栈顶下标指向的元素为push的元素,栈顶指针上移一位)
// 进栈(x为栈顶元素)
void myQueuePush(MyQueue* obj, int x) {
obj->stackIn[obj->InTop]=x;
(obj->InTop)++;//intop跟outtop都是栈顶指针,不可充当下标,但这两个指针指向的是元素的下标
}
- step③:实现pop第一位元素
需要判断stackout是否为空,否时把in栈中的元素都复制到out栈中,后pop出out栈top元素并保存
int myQueuePop(MyQueue* obj) {
// 当输出栈中原本有元素时
if(obj->OutTop!=0)
{
int top=obj->stackOut[--(obj->OutTop)];
// obj->OutTop--;
while(obj->InTop>0)
{
obj->stackOut[(obj->OutTop)++]=obj->stackIn[--(obj->InTop)];
// obj->OutTop++;
// obj->InTop--;
}
return top;
}
// 当输出栈为空时,把输入栈的数据复制到输出栈中
else
{
while(obj->InTop>0)
{
obj->stackOut[(obj->OutTop)++]=obj->stackIn[--(obj->InTop)];
// obj->InTop--;
// obj->OutTop++;
}
int top=obj->stackOut[--(obj->OutTop)];
//栈首pop
// obj->OutTop--;
// 将输出栈元素放回输入栈中
while(obj->OutTop>0)
{
obj->stackIn[(obj->InTop)++]=obj->stackOut[--(obj->OutTop)];
// obj->OutTop--;
// obj->InTop++;
}
return top;
}
}
有点啰嗦,改良版:(减少对内存的访问次数)
int myQueuePop(MyQueue* obj) {
int InTop=obj->InTop;
int OutTop=obj->OutTop;
if(OutTop==0)
{
while(InTop>0)
{
obj->stackOut[OutTop++]=obj->stackIn[--InTop];//在push元素的时候,添加一个intop数值增大1,若push入两个数字,intop大小为2,但实际上下标2指向的位置为null
// obj->stackOut[OutTop]=obj->stackIn[InTop];
// InTop--;
// OutTop++;
}
}
int result=obj->stackOut[--OutTop];
// int result=obj->stackOut[OutTop-1];
//栈首pop
// OutTop--;
// 将输出栈元素放回输入栈中
while(OutTop>0)
{
obj->stackIn[InTop++]=obj->stackOut[--OutTop];
// obj->stackIn[InTop]=obj->stackOut[OutTop];
// OutTop--;
// InTop++;
}
obj->InTop=InTop;
obj->OutTop=OutTop;
return result;
}
此时出现了错误(即注释掉的部分,导致pop出的元素一直显示越界,原因在改良代码中说明了)
误区解决:
- 实现peek获取栈底元素
// 获取栈底元素
int myQueuePeek(MyQueue* obj) {
return obj->stackIn[0];
}
- 实现判空(栈顶指针均为空时返回true)
bool myQueueEmpty(MyQueue* obj) {
if(obj->InTop==0&&obj->OutTop==0)return true;
return false;
}
简化版:
bool myQueueEmpty(MyQueue* obj) {
return obj->InTop==0&&obj->OutTop==0;
}
- 实现free(此处即栈顶指针置0)
/ 释放空间,栈顶指针置零
void myQueueFree(MyQueue* obj) {
obj->InTop=0;
obj->OutTop=0;
}
最终代码
typedef struct {
int InTop;
int OutTop;
// 创建两个栈的栈顶指针
int stackIn[100];
int stackOut[100];
// 设置两个栈的大小,题目提示不大于100
} MyQueue;
// 创建栈
MyQueue* myQueueCreate() {
//首先申请一个队列的空间
MyQueue *obj=(MyQueue*)malloc(sizeof(MyQueue));
// 初始化
obj->InTop=0;
obj->OutTop=0;
return obj;
}
// 进栈(x为栈顶元素)
void myQueuePush(MyQueue* obj, int x) {
obj->stackIn[obj->InTop]=x;
(obj->InTop)++;//intop跟outtop都是栈顶指针,不可充当下标,但这两个指针指向的是元素的下标
}
// 出栈
int myQueuePop(MyQueue* obj) {
//减少对内存的访问
int InTop=obj->InTop;
int OutTop=obj->OutTop;
if(OutTop==0)
{
while(InTop>0)
{
obj->stackOut[OutTop++]=obj->stackIn[--InTop];//在push元素的时候,添加一个intop数值增大1,若push入两个数字,intop大小为2,但实际上下标2指向的位置为null
}
}
//栈顶元素pop,并保存用于输出
int result=obj->stackOut[--OutTop];
// 将输出栈元素放回输入栈中(恢复以便后续操作)
while(OutTop>0)
{
obj->stackIn[InTop++]=obj->stackOut[--OutTop];
}
obj->InTop=InTop;
obj->OutTop=OutTop;
return result;
}
// 获取栈底元素
int myQueuePeek(MyQueue* obj) {
return obj->stackIn[0];
}
// 判断空栈,栈顶指针为0则整个栈为空,返回空即可
bool myQueueEmpty(MyQueue* obj) {
return obj->InTop==0&&obj->OutTop==0;
}
// 释放空间,栈顶指针置零
void myQueueFree(MyQueue* obj) {
obj->InTop=0;
obj->OutTop=0;
}
/**
* Your MyQueue struct will be instantiated and called as such:
* MyQueue* obj = myQueueCreate();
* myQueuePush(obj, x);
* int param_2 = myQueuePop(obj);
* int param_3 = myQueuePeek(obj);
* bool param_4 = myQueueEmpty(obj);
* myQueueFree(obj);
*/