👍作者主页:进击的1++
🤩 专栏链接:1++的数据结构初阶
一,如何用队列实现栈
1.1 什么是栈
栈是一种后进先出的数据结构,只能在栈顶进行进栈,出栈操作。关于栈的详解请看往期文章【1++的数据结构初阶】之栈。
1.2 什么是队列
队列是一种先进先出的数据结构,只能在队尾插入,在队头删除。关于队列的详解请看往期文章【1++的数据结构初阶】之队列。
1.3 用队列实现栈的原理
队列只能在队尾插入,队头删除,而栈则都是在栈顶进行插入,删除操作。因此,一个队列是不可能去实现栈的,既然一个队列无法实现,那么我们应该考虑多个队列能否实现呢?其中一个队列实现插入操作,另一个实现删除操作;或者说两个队列通过相互之间倒数据来实现栈的插入与删除。
首先要入栈时,若两个队列都为空,则随便入哪个队列都可以;否则,入队列里的非空队列;出栈时,先将非空队列里的前k-1个数据全部经出队,再进队到另一个空队列中,最后将队列里剩余的一个数据出队,就完成了出栈。
详解图如下:
二,代码实现
2.1 入栈的实行
typedef int QDatatype;
typedef struct Node
{
struct Node* next;
QDatatype data;
}Node;
typedef struct Queue
{
Node* head;
Node* tail;
int size;
}Queue;
void QInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QDestroy(Queue* pq)
{
assert(pq);
Node* cur = pq->head;
while (cur != NULL)
{
Node* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QPush(Queue* pq , QDatatype x)
{
assert(pq);
Node* tmp = (Node*)malloc(sizeof(Node));
if (tmp == NULL)
{
perror("malloc fail");
exit(-1);
}
Node* newnode = tmp;
newnode->next = NULL;
newnode->data = x;
if (pq->head==NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
void QPop(Queue* pq)
{
assert(pq);
assert(pq->head!=NULL);
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
Node* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
bool QEmpty(Queue* pq)
{
assert(pq);
return pq->size == 0;
}
int QSize(Queue* pq)
{
assert(pq);
return pq->size;
}
QDatatype QFront(Queue* pq)
{
assert(pq);
assert(!QEmpty(pq));
return pq->head->data;
}
QDatatype QBack(Queue* pq)
{
assert(pq);
assert(!QEmpty(pq));
return pq->tail->data;
}
typedef struct MyStack
{
Queue* q;
Queue* p;
}MyStack;
MyStack* CreatMyStack()
{
MyStack* obj =(MyStack*)malloc(sizeof(MyStack));
assert(obj);
QInit(&obj->p);
QInit(&obj->q);
return obj;
}
void MyStackPush(MyStack* obj,QDatatype x)
{
assert(obj);
if(QEmpty(&obj->p))
{
QPush(&obj->p,x);
}
else
{
QPush(&obj->q, x);
}
}
2.2 出栈的实行
bool MyStackEmpty(MyStack* obj)
{
return (QEmpty(&obj->p) == NULL && QEmpty(&obj->q) == NULL);
}
void MyStackPop(MyStack* obj)
{
assert(obj);
assert(!MyStackEmpty(obj));
//将数据挪到另一个空队列
Queue* empt = &obj->p;
Queue* fill = &obj->q;
if (QEmpty(&obj->q))
{
empt = &obj->q;
fill = &obj->p;
}
while (QSize(fill) > 1)
{
QPush(empt, QFront(fill));
QPop(fill);
}
QPop(fill);
}
2.3 出栈顶及其销毁栈
int MyStackTop(MyStack* obj)
{
assert(obj);
if (!QEmpty(&obj->p))
{
return QBack(&obj->p);
}
else
{
return QBack(&obj->q);
}
}
void myStackFree(MyStack* obj)
{
assert(obj);
QDestroy(&obj->q);
QDestroy(&obj->p);
free(obj);
}
三,总结
本篇文章主要难点在于结构,代码本身没有什么难度,在学习本篇文章前建议对队列及栈有较好的基础与理解,如果读者觉得本篇文章不错,希望能够点赞分享,若发现文章有不足之处及错误,欢迎指正。