用两个队列实现一个栈and用两个栈实现一个队列
Posted 李有鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用两个队列实现一个栈and用两个栈实现一个队列相关的知识,希望对你有一定的参考价值。
目录
一、用两个队列实现一个栈
1.1 问题描述
oj链接:225. 用队列实现栈 - 力扣(LeetCode)
1.2 问题分析
用两个队列来实现栈,首先我们需要了解栈和队列这两种结构各自的特点,栈要求先入后出,队列要求先进先出。
也就是说,用两个队列来模拟实现栈,主要是使用两个队列来完成先入后出的功能,而队列的特点是先入先出,在这里我们主要说明的是入栈和出栈操作:
对于入栈:
对于出栈:
总结起来即以下几点:
- 定义一个结构体Stack,包含两个队列q1和q2。
- 初始化栈时,分别初始化两个队列。
- 入栈操作时,将元素插入非空的队列中。
- 出栈操作时,将非空队列中的元素依次出队并插入另一个空队列中,直到只剩下一个元素,然后将该元素出队即可。
- 取栈顶元素时,将非空队列中的元素依次出队并插入另一个空队列中,直到只剩下一个元素,然后返回该元素即可。
- 判断栈是否为空时,判断两个队列是否都为空即可。
1.3 代码
typedef int QDatatype;
typedef struct QueueNode
struct QueueNode* next;
QDatatype data;
QNode;
typedef struct Queue
QNode* head;
QNode* tail;
int size;
Queue;
//初始化函数
void QueueInit(Queue* pq)
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
//销毁
void QueueDestroy(Queue* pq)
assert(pq);
QNode* cur = pq->head;
while (cur)
QNode* next = cur->next;
free(cur);
cur = next;
pq->head = pq->tail = NULL;
pq->size = 0;
//入队列
void QueuePush(Queue* pq, QDatatype x)
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
perror("malloc fail");
return;
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)
assert(pq->tail == NULL);
pq->head = pq->tail = newnode;
else
pq->tail->next = newnode;
pq->tail = newnode;
pq->size++;
//判断是否为空
bool QueueEmpty(Queue* pq)
assert(pq);
return pq->size == 0;
//出队列
void QueuePop(Queue* pq)
assert(pq);
assert(!(QueueEmpty(pq)));
if (pq->head == pq->tail)
free(pq->head);
pq->head = pq->tail = NULL;
else
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
pq->size--;
//求队列的元素个数
int QueueSize(Queue* pq)
assert(pq);
return pq->size;
//返回队首元素
QDatatype QueueFront(Queue* pq)
assert(pq);
assert(!(QueueEmpty(pq)));
return pq->head->data;
//返回队尾元素
QDatatype QueueBack(Queue* pq)
assert(pq);
assert(!(QueueEmpty(pq)));
return pq->tail->data;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq,QDatatype x);
void QueuePop(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);
typedef struct
Queue q1;
Queue q2;
MyStack;
MyStack* myStackCreate()
MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
if(pst==NULL)
perror("malloc fail");
return NULL;
QueueInit(&pst->q1);
QueueInit(&pst->q2);
return pst;
void myStackPush(MyStack* obj, int x)
if(!QueueEmpty(&obj->q1))
QueuePush(&obj->q1, x);
else
QueuePush(&obj->q2, x);
bool myStackEmpty(MyStack* obj)
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
int myStackPop(MyStack* obj)
assert(!myStackEmpty(obj));
Queue* nonemptyque = &obj->q1;
Queue* emptyque = &obj->q2;
if(QueueEmpty(&obj->q1))
nonemptyque = &obj->q2;
emptyque = &obj->q1;
while(QueueSize(nonemptyque)>1)
QueuePush(emptyque,QueueFront(nonemptyque));
QueuePop(nonemptyque);
int x = QueueFront(nonemptyque);
QueuePop(nonemptyque);
return x;
int myStackTop(MyStack* obj)
assert(!myStackEmpty(obj));
Queue* nonemptyque = &obj->q1;
Queue* emptyque = &obj->q2;
if(QueueEmpty(&obj->q1))
nonemptyque = &obj->q2;
emptyque = &obj->q1;
return QueueBack(nonemptyque);
void myStackFree(MyStack* obj)
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
二、用两个栈实现一个队列
2.1 问题描述
oj链接:232. 用栈实现队列 - 力扣(LeetCode)
2.2 问题分析
我们要用两个栈来实现一个队列,栈的特点是先入后出,队列的特点是先入先出,我们这里的目的是使用两个栈达到先入先出的目的。
与之前的用两个队列来实现栈,用两个栈来实现队列相对简单,在之前的用两个队列来实现栈,我们在出栈时需要把两个队列中的数据来回翻转,但在本题中,我们只需要定义一个栈来进行插入操作,一个用来删除。
我们固定使用栈q1来进行入队操作,使用栈q2来进行出队操作。
入队时:
直接将数据插入到q1中。
出队时:
当q2为空时,再次将q1中数据依次出栈,然后依次插入到栈q2中。
具体总结如下:
- 定义一个结构体Queue,包含两个栈s1和s2。
- 初始化队列时,分别初始化两个栈。
- 入队操作时,将元素插入非空的栈s1中。
- 出队操作时,如果栈s2为空,则将栈s1中的元素依次出栈并插入栈s2中,然后将栈s2的栈顶元素出栈即可。
- 取队首元素时,如果栈s2为空,则将栈s1中的元素依次出栈并插入栈s2中,然后返回栈s2的栈顶元素即可。
- 判断队列是否为空时,判断两个栈是否都为空即可。
2.3 代码
typedef int STDataType;
#define N 4
typedef struct Stack
STDataType* a;
int top;
int capacity;
ST;
void STInit(ST* ps);
void STDestroy(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
int STsize(ST* ps);
bool STEmpty(ST* ps);
STDataType STTop(ST* ps);
//初始化函数
void STInit(ST* ps)
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType)*N);
if (ps->a == NULL)
perror("malloc fail");
return;
ps->top = 0;
ps->capacity = N;
//销毁
void STDestroy(ST* ps)
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
//求栈中的元素
int STsize(ST* ps)
assert(ps);
return ps->top;
//入栈
void STPush(ST* ps, STDataType x)
assert(ps);
if (STsize(ps) == ps->capacity)
STDataType* p = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);
if (p == NULL)
perror("realloc fail");
return;
ps->a = p;
ps->capacity *= 2;
ps->a[ps->top] = x;
ps->top++;
//判断栈是否为空
bool STEmpty(ST* ps)
assert(ps);
return ps->top == 0;
//出栈
void STPop(ST* ps)
assert(ps);
assert(!STEmpty(ps));
ps->top--;
//取出栈顶元素
STDataType STTop(ST* ps)
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top - 1];
typedef struct
ST q1;
ST q2;
MyQueue;
MyQueue* myQueueCreate()
MyQueue* pst = (MyQueue*)malloc(sizeof(MyQueue));
if(pst==NULL)
perror("malloc fail");
return NULL;
STInit(&pst->q1);
STInit(&pst->q2);
return pst;
void myQueuePush(MyQueue* obj, int x)
STPush(&obj->q1, x);
bool myQueueEmpty(MyQueue* obj)
return STEmpty(&obj->q1)&&STEmpty(&obj->q2);
int myQueuePop(MyQueue* obj)
assert(!myQueueEmpty(obj));
if(STEmpty(&obj->q2))
while(STsize(&obj->q1)>0)
STPush(&obj->q2, STTop(&obj->q1));
STPop(&obj->q1);
int x= STTop(&obj->q2);
STPop(&obj->q2);
return x;
else
int x= STTop(&obj->q2);
STPop(&obj->q2);
return x;
int myQueuePeek(MyQueue* obj)
assert(!myQueueEmpty(obj));
if(STEmpty(&obj->q2))
while(STsize(&obj->q1)>0)
STPush(&obj->q2, STTop(&obj->q1));
STPop(&obj->q1);
int x= STTop(&obj->q2);
return x;
else
int x= STTop(&obj->q2);
return x;
void myQueueFree(MyQueue* obj)
STDestroy(&obj->q1);
STDestroy(&obj->q2);
free(obj);
用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
思路:
一个栈存储元素,一个栈辅助
维护两个栈,第一个栈存储元素,第二个栈用于辅助操作。
根据栈的特性,第一个栈的底部元素是最后插入的元素,第一个栈的顶部元素是下一个被删除的元素。为了维护队列的特性,每次插入的元素应该在第一个栈的底部。因此每次插入元素时,若第一个栈内已经有元素,应将已有的全部元素依次弹出并压入第二个栈,然后将新元素压入第一个栈,最后将第二个栈内的全部元素依次弹出并压入第一个栈。经过上述操作,新插入的元素在第一个栈的底部,第一个栈内的其余元素的顺序和插入元素之前保持一致。
删除元素时,若第一个栈非空,则直接从第一个栈内弹出一个元素并返回,若第一个栈为空,则返回 -1。
另外维护队列的元素个数,用于判断队列是否为空。初始元素个数为 0。每次插入元素,元素个数加 1。每次删除元素,元素个数减 1。
#include<iostream> #include<stack> using namespace std; stack<int> st1,st2; //初始化,读取数据 void init(stack<int> & st1){ int n,num; cin>>n; for (int i = 0; i < n; i++) { cin>>num; st1.push(num); } } //在对队尾加上元素,实际上是一个栈的栈顶 void appendTail(int value){ st1.push(value); } //删除队列开头的元素 int deleteHead(){ //队空 if (st1.empty()) return -1; //先把存储元素的栈反向保存到辅助栈st2,此时在栈顶的元素就是队头 while (!st1.empty()) { st2.push(st1.top()); st1.pop(); } //删除对头 st2.pop(); //保存到存储数据的栈st1 while(!st2.empty()){ st1.push(st2.top()); st2.pop(); } return 1; } //栈的遍历 void PrintValue(stack<int> st1){ while(!st1.empty()){ cout<<st1.top()<<" "; st1.pop(); } cout<<endl; } //测试代码main() int main(){ init(st1); PrintValue( st1); appendTail(0); appendTail(-1); PrintValue( st1); deleteHead(); PrintValue( st1); }
以上是关于用两个队列实现一个栈and用两个栈实现一个队列的主要内容,如果未能解决你的问题,请参考以下文章