Este artigo é uma compreensão mais profunda de filas e pilhas, e usa suas próprias propriedades para concluir a conversão entre elas.Antes disso, você deve entender claramente sua implementação e aplicação.
contente
Implementando pilhas com filas
Análise de implementação da pilha:
Definir pilha e inicialização de pilha
Elemento na pilha (enfileirar)
Elemento aparece (desenfileirar)
retorna o elemento do topo da pilha
Determinando se a pilha está vazia e destruindo a pilha
Link da pergunta: 225. Implementando uma pilha com uma fila - LeetCode (leetcode-cn.com)
Implementando pilhas com filas
Implementamos uma fila com uma lista encadeada simples antes. Sabemos que sua natureza é primeiro a entrar, primeiro a sair. Como usar duas filas para implementar uma pilha? Duas FIFOs podem ser usadas para concluir um último a entrar, primeiro a pilha fora? Agora vamos completar a primeira pergunta: Implementando uma pilha com uma fila
Escrita da fila:
Lendo a pergunta, podemos ver que devemos primeiro concluir a definição da fila. Este problema é concluído na premissa de ter uma fila. A fila já foi implementada antes, para que possamos concluir diretamente a escrita da fila:
typedef int QDatatype;
//定义单链表结点
typedef struct QueueNode
{
QDatatype data;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
void QueuePush(Queue* pq,QDatatype x);
void QueuePop(Queue* pq);
bool QueueEmpty(Queue* pq);
size_t QueueSize(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);
//队列初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
}
//队列销毁
void QueueDestory(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
//队尾插入
void QueuePush(Queue* pq, QDatatype x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
assert(newnode);
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;
}
}
//队头删除
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->head&&pq->tail);
if (pq->head->next==NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
}
//判断是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL&&pq->tail == NULL;
}
//队列元素个数
size_t QueueSize(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
size_t size = 0;
while (cur)
{
size++;
cur = cur->next;
}
return size;
}
//对头元素
QDatatype QueueFront(Queue* pq)
{
assert(pq);
assert(pq->head);
return pq->head->data;
}
//队尾元素
QDatatype QueueBack(Queue* pq)
{
assert(pq);
assert(pq->tail);
return pq->tail->data;
}
Análise de implementação da pilha:
A fila é o primeiro a entrar, o primeiro a sair, e o início e o fim são operados. Como as duas filas implementam uma pilha de último a entrar? Dessa forma, você pode não saber o que isso vai fazer. Simplificando:
Enfio 1 2 3 4 5 na fila, como posso tirá-lo da fila 5 4 3 2 1, em duas filas.
O diagrama é o seguinte:
Definir pilha e inicialização de pilha
Definição: A pilha é implementada por duas filas encapsuladas.
Inicialização: primeiro crie espaço para a pilha para determinar se a criação foi bem-sucedida e, em seguida, inicialize as duas filas na pilha, usando a função de inicialização quando definimos a fila.
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* pst=(MyStack*)malloc(sizeof(MyStack));
assert(pst);
QueueInit(&pst->q1);
QueueInit(&pst->q2);
return pst;
}
Elemento na pilha (enfileirar)
Julgue se as duas filas estão vazias, enfileire os dados na fila não vazia e mantenha a fila vazia para facilitar a importação de dados para frente e para trás.
void myStackPush(MyStack* obj, int x) {
assert(obj);
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
Elemento aparece (desenfileirar)
Defina duas filas, vazias e não vazias, e atribua-as a 12 filas de cada vez para facilitar as operações subsequentes.
Cada vez que os primeiros elementos Size-1 da fila não vazia são importados para a fila vazia, os dados originais da fila não vazia são excluídos e o último elemento é retirado da fila para concluir o desempilhamento.
Preste atenção aos detalhes: retorne o elemento do topo da pilha, o topo da pilha é o elemento final da fila não vazia e, em seguida, retire o elemento final não vazio, ou seja, o topo da pilha.
int myStackPop(MyStack* obj) {
assert(obj);
//判断空和非空是哪个
Queue* emptyQ=&obj->q1;
Queue* nonemptyQ=&obj->q2;
if(!QueueEmpty(&obj->q1))
{
emptyQ=&obj->q2;
nonemptyQ=&obj->q1;
}
//把非空队列前N个数据导入空队列
//剩下一个删除实现后进先出
while(QueueSize(nonemptyQ)>1)
{
QueuePush(emptyQ,QueueFront(nonemptyQ));
QueuePop(nonemptyQ);
}
int top=QueueFront(nonemptyQ);
QueuePop(nonemptyQ);
return top;
}
retorna o elemento do topo da pilha
Julgando encontrar uma fila não vazia, você pode se opor diretamente ao elemento final da fila não vazia, e a cauda da fila é o topo da pilha.
int myStackTop(MyStack* obj) {
assert(obj);
if(!QueueEmpty(&obj->q1))
{
return QueueBack(&obj->q1);
}
else
{
return QueueBack(&obj->q2);
}
}
Determinando se a pilha está vazia e destruindo a pilha
Julgamento: A pilha tem duas filas, e a pilha está vazia quando ambas as filas estão vazias, basta retornar.
Destruição: Existem duas filas na pilha, e as duas filas também apontam para dois espaços. Ao destruir, as filas são destruídas primeiro para evitar vazamentos de memória.
bool myStackEmpty(MyStack* obj) {
assert(obj);
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj) {
assert(obj);
QueueDestory(&obj->q1);
QueueDestory(&obj->q2);
free(obj);
}