思路
思路:利用两个栈实现队列先进先出的特性,先将元素导入一个栈内
模拟出队时,则将所有元素导入另一个栈内,此时元素顺序被反转过来,只需要取栈顶数据即可
那我们就可以将两个栈的功能分开,一个专门入push,一个专门出pop。出数据时,如果popst为空,则将pushst的数据导入。
假设pushst入了1234后,反转到popst后,pushst又入了56,这时也是可以的。因为先pop4次,将1 2 3 4依次出栈,popst为空,则再将56导入,再pop2次,以5 6依次出栈。最终依然是1 2 3 4 5 6先入先出的顺序。
实现
实现: 因为C语言没有库可以现成使用,所以我们将写好的栈导入
先创建MyQueue结构体,包含两个栈结构体。再malloc动态申请MyQueue结构体的空间,最后将两个栈传入初始化函数,进行初始化(记得要加上&取地址符号)
入队过程 ,我们把数据全部导入pushst栈内即可
因为peek的功能比较简单,只用返回队列开头元素,所以我们先实现这个功能,等会实现pop再复用peek。
返回队列开头元素,我们的核心思路,先判断popst是否为空,如果为空,则循环将pushst中的元素全部导入popst(注意:每取出一个栈顶元素,就将该元素pop出栈),最后获取popst的栈顶元素即可
出队过程,复用peek的功能,先用front保存队头元素,再将popst的栈顶元素弹出,最后返回front即可
判断栈是否为空,只要当两个栈pushst和popst全为空时,队列才为空,返回true,否则返回false
最后,释放队列空间,可能有人只写了最后一句也给过了,但是其实这是不对的。正确做法是,先将两个栈都销毁(销毁数组),再将MyQueue空间给释放掉,这样才不会造成内存泄漏
完整代码附上:
typedef int STDataType; typedef struct Stack { STDataType* a; int top; int capacity; }ST; //初始化 void STInit(ST* pst); //销毁 void STDestroy(ST* pst); //压栈 void STPush(ST* pst, STDataType x); //出栈 void STPop(ST* pst); //获取栈顶元素 STDataType STTop(ST* pst); //检测栈是否为空 bool STEmpty(ST* pst); //检测栈中有效元素个数 int STSize(ST* pst); void STInit(ST* pst) { assert(pst); pst->a = NULL; pst->top = 0;//top指向栈顶元素的下一个位置 pst->capacity = 0; } void STDestroy(ST* pst) { assert(pst); free(pst->a); pst->top = pst->capacity = 0; } void STPush(ST* pst, STDataType x) { assert(pst); if (pst->top == pst->capacity) { int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2; STDataType* tmp = (STDataType*)realloc(pst->a, newCapacity * sizeof(STDataType)); if (tmp == NULL) { perror("realloc fail"); return; } pst->a = tmp; pst->capacity = newCapacity; } pst->a[pst->top++] = x; } void STPop(ST* pst) { assert(pst); assert(!STEmpty(pst)); pst->top--; } STDataType STTop(ST* pst) { assert(pst); assert(!STEmpty(pst)); return pst->a[pst->top - 1]; } bool STEmpty(ST* pst) { assert(pst); return pst->top == 0; } int STSize(ST* pst) { assert(pst); return pst->top; } typedef struct { ST pushst; ST popst; } MyQueue; MyQueue* myQueueCreate() { MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue)); if (obj == NULL) { perror("malloc fail"); return NULL; } STInit(&obj->pushst); STInit(&obj->popst); return obj; } void myQueuePush(MyQueue* obj, int x) { STPush(&obj->pushst, x); } int myQueuePop(MyQueue* obj) { int front = myQueuePeek(obj); STPop(&obj->popst); return front; } int myQueuePeek(MyQueue* obj) { if (STEmpty(&obj->popst)) { while (!STEmpty(&obj->pushst)) { STPush(&obj->popst, STTop(&obj->pushst)); STPop(&obj->pushst); } } return STTop(&obj->popst); } bool myQueueEmpty(MyQueue* obj) { return STEmpty(&obj->pushst) && STEmpty(&obj->popst); } void myQueueFree(MyQueue* obj) { STDestroy(&obj->pushst); STDestroy(&obj->popst); free(obj); } /** * 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); */