Duas pilhas podem ser implementadas com eficiência usando uma matriz de tamanho fixo: a pilha nº 1 começa na extremidade esquerda e cresce para a direita e a pilha nº 2 começa na extremidade direita e cresce para a esquerda. O mesmo é possível para três pilhas?
Mais especificamente, é possível implementar três pilhas, dadas as seguintes condições:
- Você tem uma matriz de tamanho fixo que pode conter N objetos.
- Contanto que a soma dos três tamanhos de pilha seja <N, push () não deve falhar.
- As operações push () e pop () devem levar tempo O (1).
- Além da matriz, você pode usar apenas O (1) espaço adicional.
Aqui estão exemplos de soluções que não atendem a esses requisitos:
- Dividir a matriz em 3 partes fixas e usar cada parte de uma pilha (viola 2).
- Semelhante ao anterior, mas com limites móveis entre as pilhas (viola 3).
- Implementações simples baseadas em lista vinculada (viola 4).
Aceitarei algoritmos não triviais ou provas de impossibilidade, mesmo que eles não atendam a todas as condições (1) - (4) exatamente, por exemplo, um algoritmo em que push / pop leve O (1) tempo amortizado ou onde o a memória adicional é menor que O (N), por exemplo, O (log N). Ou uma prova de impossibilidade que mostre que, por exemplo, acessar menos de 5 elementos da matriz por push / pop é impossível.
fonte
Respostas:
Fredman e Goldsmith mostraram em "Três pilhas" (Journal of Algorithms, 1994) que bits de espaço desperdiçado são alcançáveis. Também é o mínimo necessário para matrizes de tamanho de pelo menos 16 quattuordecillion yottabytes. Descrevi um algoritmo simples que desperdiçou palavras de espaço na minha resposta StackOverflow a esta pergunta . Como @ dmitri-urbanowicz mencionado nos comentários, isso basicamente trata apenas a matriz como blocos de tamanho , onde cada bloco é usado para exatamente uma pilha e contém um único ponteiro para o próximo bloco nessa pilha.Θ(nε) Θ(n−−√) √n−−√ n−−√
fonte
Seja N o comprimento da matriz subjacente. Posso imaginar pilhas como listas vinculadas de grandes pedaços, de modo que o número geral de pedaços não seja maior que O (log2 (N)). Coloque a terceira pilha entre as duas primeiras, no índice de N / 2. Portanto, temos 3 áreas ocupadas e 2 gratuitas. Quando uma pilha não pode aceitar o próximo elemento, isso significa que uma área livre está esgotada. Se o outro também estiver exausto, toda a memória estará exausta. Caso contrário, há outra área livre com tamanho não superior a N / 2. Continue a pilha excedida para essa área livre. para que toda a configuração se assemelhe ao layout inicial das pilhas. Como a memória livre agora não passa da metade da inicial, não haverá mais que o log2 (N) dessas operações de vinculação. Cada operação de vinculação requer uma quantidade fixa de memória para salvar o estado anterior da pilha. Assim,
fonte