Uma pergunta semelhante foi perguntado mais cedo lá , mas a questão aqui é o inverso disso, usando duas filas como uma pilha. A questão...
Dadas duas filas com suas operações padrão ( enqueue
, dequeue
, isempty
, size
), implementar uma pilha com suas operações padrão ( pop
, push
, isempty
, size
).
Deve haver duas versões da solução.
- Versão A : A pilha deve ser eficiente ao empurrar um item; e
- Versão B : a pilha deve ser eficiente ao exibir um item.
Estou interessado no algoritmo mais do que em qualquer implementação de linguagem específica. No entanto, saúdo as soluções expressas em idiomas que eu conheço (Java,c #,Pitão,vb,javascript,php)
algorithm
data-structures
stack
TechTravelThink
fonte
fonte
Pop
funciona em $ O (1) $ ePush
funciona em $ O (\ sqrt {n}) $ tempo amortizado.Respostas:
Versão A (envio eficiente):
Versão B (pop eficiente):
fonte
A maneira mais fácil (e talvez única) de fazer isso é empurrar novos elementos para a fila vazia e, em seguida, desenfileirar o outro e entrar na fila anteriormente vazia. Dessa maneira, o mais recente está sempre na frente da fila. Essa seria a versão B, para a versão A, você acabou de reverter o processo desenfileirando os elementos na segunda fila, exceto a última.
Etapa 0:
Passo 1:
Passo 2:
Etapa 3:
fonte
Podemos fazer isso com uma fila:
empurrar:
n
for o número de elementos na fila, remova e insira asn-1
horas do elemento .pop:
.
Exemplo de implementação:
fonte
fonte
Podemos apenas usar uma fila para implementar uma pilha? Posso usar duas filas, mas considerar a fila única seria mais eficiente. Aqui está o código:
fonte
fonte
Aqui está a minha resposta - onde o 'pop' é ineficiente. Parece que todos os algoritmos que vêm imediatamente à mente têm complexidade N, onde N é o tamanho da lista: se você escolhe trabalhar no 'pop' ou no 'push'
O algoritmo em que as listas são negociadas de volta e a quarta pode ser melhor, pois não é necessário um cálculo de tamanho, embora você ainda precise fazer um loop e comparar com vazio.
você pode provar que esse algoritmo não pode ser gravado mais rápido que N, observando que as informações sobre o último elemento de uma fila estão disponíveis apenas através do conhecimento do tamanho da fila e que você deve destruir os dados para chegar a esse elemento, daí a segunda fila .
A única maneira de tornar isso mais rápido é não usar filas em primeiro lugar.
fonte
Aqui está a minha solução que funciona para O (1) em média. Existem duas filas:
in
eout
. Veja pseudocódigo abaixo:fonte
Como já foi mencionado, uma única fila não funcionaria? Provavelmente é menos prático, mas é um pouco mais lento.
fonte
Aqui está um pseudo-código simples, push é O (n), pop / peek é O (1):
fonte
Seja S1 e S2 as duas pilhas a serem usadas na implementação de filas.
Garantimos que uma fila esteja sempre vazia.
Operação push: qualquer fila que não estiver vazia, insira o elemento nela.
Push (struct Stack *S, int data) { if(isEmptyQueue(S->Q1) EnQueue(S->Q2, data); else EnQueue(S->Q1, data); }
Complexidade de tempo: O (1)
Operação pop: transfira os elementos n-1 para outra fila e exclua o último da fila para executar a operação pop.
`
Complexidade do tempo: tempo de execução da operação pop é O (n), cada vez que a pop é chamada, estamos transferindo todos os elementos de uma fila para outro.
fonte
fonte
fonte
Aqui está mais uma solução:
para PUSH: -Adicione o primeiro elemento na fila 1.-Ao adicionar o segundo elemento e assim por diante, enfileire o elemento na fila 2 primeiro e depois copie todo o elemento da fila 1 para a fila2. -para o POP apenas desenfileirar o elemento da fila de você inseriu o último elemento.
Assim,
}}
Há um problema, não consigo descobrir, como renomear as filas ???
fonte
fonte
Código Python usando apenas uma fila
fonte
aqui está o código completo de trabalho em c #:
Foi implementado com fila única,
empurrar:
pop:
fonte
Aqui está uma solução muito simples que usa uma fila e fornece funcionalidades como a pilha.
Portanto, na classe acima denominada "CustomStack", o que estou fazendo é apenas verificar se há vazio na fila, se vazio, em seguida, insira um e a partir de então, insira e remova o inserto. Por essa lógica, o primeiro virá por último. Exemplo: Na fila, inseri 1 e agora estou tentando inserir 2. Na segunda vez, remova 1 e insira novamente para que fique na ordem inversa.
Obrigado.
fonte
Abaixo está uma solução Java muito simples que suporta a operação push eficiente.
Algoritmo -
Declare duas filas q1 e q2.
Operação push - enfileirar o elemento na fila q1.
Operação pop - Verifique se a fila q2 não está vazia. Se estiver vazio, desenfileire todos os elementos de q1, exceto o último elemento, e enfileire-o em q2, um por um. Retire da fila o último elemento de q1 e armazene-o como o elemento popped. Troque as filas q1 e q2. Retorne o elemento popped armazenado.
Peek operation - Verifique se a fila q2 não está vazia. Se estiver vazio, desenfileire todos os elementos de q1, exceto o último elemento, e enfileire-o em q2, um por um. Retire da fila o último elemento de q1 e armazene-o como o elemento espiado. Coloque-o novamente na fila q2 e troque as filas q1 e q2. Retorne o elemento espiado armazenado.
Abaixo está o código do algoritmo acima -
fonte
Aqui está a minha solução ..
Concept_Behind ::
push(struct Stack* S,int data)
:: Essa função enfileira o primeiro elemento no Q1 e permanece no Q2pop(struct Stack* S)
:: se Q2 não estiver vazio, transfere todos os elem para Q1 e retorna o último elem em Q2, caso contrário, o que significa que Q2 está vazio retorna o último elem no primeiro trimestreEfficiency_Behind ::
push(struct Stack*S,int data)
:: O (1) // desde o enfileiramento único por dadospop(struct Stack* S)
:: O (n) //, pois transfere os piores dados n-1 por pop.fonte
fonte
fonte