P. 1
BF26Dd01

BF26Dd01

|Views: 6|Likes:
Published by Rafael Freitas

More info:

Published by: Rafael Freitas on Jul 06, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

02/16/2014

pdf

text

original

FEUP/LEEC Algoritmos e Estruturas de Dados 2001/2002

Pilhas e Filas

João Canas Ferreira http://www.fe.up.pt/~jcf

FEUP/LEEC,AED,2001/2002, v0.1

Pilhas e Filas

#1

Conteúdo
1. Pilhas (a) Implementação baseada em listas (b) Implementação baseada em vectores 2. Filas (a) Implementação baseada em listas (b) Implementação baseada em vectores 3. Aplicações de pilhas (a) Cálculo de expressões RPN (b) Conversão de expressões infixas para RPN 4. Aplicação de filas (a) Percurso mais curto num labirinto

FEUP/LEEC,AED,2001/2002, v0.1

Pilhas e Filas

#2

1

Uma pilha pode ser considerada como uma restrição de lista. Visto que se trata de uma estrutura de dados mais simples que a lista.1 Pilhas e Filas #3 Operações com pilhas 1 2 3 4 5 5 1 2 3 4 5 3 2 1 1 2 1 4 3 2 1 4 3 2 1 5 4 3 2 2 5 4 3 2 1 4 3 2 1 3 2 1 2 1 1 5 4 3 2 1 FEUP/LEEC.1 Pilhas e Filas #4 2 . O conceito de iterador não se aplica a esta estrutura de dados. v0. v0.2001/2002.AED. é possível obter implementações mais eficazes. geralmente designada por topo da pilha.2001/2002.AED. LIFO = Last-in First-out FEUP/LEEC.Pilhas Pilha Estrutura de dados em que a inserção e a remoção de elementos de uma sequência se faz pela mesma extremidade.

private: class ListNode // classe privada { public: T element. const LStack & operator=(const LStack &stk).2001/2002. ListNode *next. Pilhas e Filas #5 FEUP/LEEC. LStack(const LStack &stk). ListNode *n = 0) : element(elem). T topAndPop(). const T & top() const.. v0. FEUP/LEEC.. ListNode *topOfStack.1 Pilhas e Filas #6 3 . }. ~LStack(). bool isFull() const. void push(const T &x).1 Classe LStack – Secção privada template <class T> class LStack { // . next(n) { }. v0. }.AED. void makeEmpty()..Pilha – Implementação baseada em listas template <class T> class LStack { public: LStack().2001/2002.. bool isEmpty() const.AED. ///. void pop(). ListNode(const T & elem.

v0. v0. pop(). delete oldTop.2001/2002. } FEUP/LEEC. } FEUP/LEEC.AED.2001/2002. } template <class T> T LStack<T>::topAndPop() { T topItem = top(). return topItem.push() e top() template <class T> void LStack<T>::push(const T &x) { topOfStack = new ListNode(x. return topOfStack->element.AED.1 Pilhas e Filas #7 pop() e topAndPop() template <class T> void LStack<T>::pop() { if (isEmpty()) throw Underflow().1 Pilhas e Filas #8 4 . topOfStack = topOfStack->next. } template <class T> const T & LStack<T>::top() const { if (isEmpty()) throw Underflow(). ListNode *oldTop = topOfStack. topOfStack).

}.Pilhas–Implementação baseada em vectores template <class T> class VStack { public: explicit VStack(int capacity = 100). v0..2001/2002. v0. void makeEmpty(). private: vector<T> theArray. //..AED.AED. T topAndPop().. void pop().2001/2002.1 Pilhas e Filas #9 VStack – Secção privada template <class T> class VStack { // .1 Pilhas e Filas # 10 5 .. bool isEmpty() const. int topOfStack. void push(const T &x). const T & top() const. topOfStack =3 VAZIO topOfStack = -1 FEUP/LEEC. bool isFull() const. FEUP/LEEC. Atenção: Não deixar o vector aumentar de tamanho.

2001/2002. } template <class T> T VStack<T>::topAndPop() { if (isEmpty()) throw Underflow(). } FEUP/LEEC. } Pilhas e Filas # 12 FEUP/LEEC. return theArray[topOfStack]. return theArray[topOfStack--]. v0. theArray[++topOfStack] = x. } template <class T> void VStack<T>::push(const T &x) { if (isFull()) throw Overflow().Classe VStack – Implementação template <class T> bool VStack<T>::isFull() const { return topOfStack == theArray.AED. } template <class T> void VStack<T>::makeEmpty() { topOfStack = -1.2001/2002. v0.AED.size() .1.1 6 . } template <class T> void VStack<T>::pop() { if (isEmpty()) throw Underflow(). topOfStack--.1 Pilhas e Filas # 11 Classe VStack – pop() e top() template <class T> const T & VStack<T>::top() const { if (isEmpty()) throw Underflow().

v0. O conceito de iterador não se aplica a esta estrutura de dados.1 Pilhas e Filas # 14 7 . geralmente designadas por cabeça e cauda da fila.AED.Filas Fila Estrutura de dados em que a inserção e a remoção de elementos de uma sequência se faz por extremidades opostas. Visto que se trata de uma estrutura de dados mais simples que a lista.AED.2001/2002.2001/2002. Uma fila pode ser considerada como uma restrição de lista. FIFO = First-in First-out FEUP/LEEC.1 Pilhas e Filas # 13 Funcionamento de filas 12345 1 1 2 3 4 5 1 2 2 3 4 5 1 2 3 3 4 5 1 2 3 4 4 5 1 2 3 4 5 5 1 2 3 4 5 FEUP/LEEC. v0. é possível obter implementações mais eficazes.

void dequeue().2001/2002. v0. }. // . ~LQueue(). const T & getFront() const. Pilhas e Filas # 16 FEUP/LEEC.AED.1 8 .. bool isFull() const. void makeEmpty(). bool isEmpty() const.AED.1 Pilhas e Filas # 15 Classe LQueue – secção pública template <class T> class LQueue { public: LQueue().2001/2002. v0.. const LQueue & operator=(const LQueue &stk). LQueue(const LQueue &stk).Filas – Implementação com listas LQueue<char> back front a b c d FEUP/LEEC. void enqueue(const T &x).

ListNode *next.AED. ListNode(const T & elem. FEUP/LEEC. private: class ListNode { public: T element. if (oldBack) oldBack->next = back.AED.1 Pilhas e Filas # 17 Classe LQueue – enqueue() e dequeue template <class T> void LQueue<T>::enqueue(const T &x) { ListNode *oldBack = back. }. if (!front) back = 0. if (!front) front = back.Classe LQueue – secção privada template <class T> class LQueue { // . ListNode *oldFront = front.2001/2002.1 9 . }.2001/2002. *back. front = front->next. 0). v0. delete oldFront. back = new ListNode(x. next(n) { }. ListNode *front. } Pilhas e Filas # 18 FEUP/LEEC. v0... } template <class T> void LQueue<T>::dequeue() { if (isEmpty()) throw Underflow(). ListNode *n = 0) : element(elem).

private: vector<T> theArray... Pilhas e Filas # 20 FEUP/LEEC. int front.2001/2002. void increment(int &x).1 Pilhas e Filas # 19 Classe CQueue – secção privada template <class T> class CQueue { public: explicit CQueue(int capacity = 100).Filas – Implementação com vectores Importante: Evitar deslocar os elementos do vector.AED. back. int currentSize. // . mas facilita bastante a gestão da estrutura. v0.AED.1 10 . tirar ’a’ a b c d back colocar ’e’ tirar ’b’ b c d e back colocar ’f’ tirar ’c’ f c d e f d e c d e b c d back front front front front back back front back front FEUP/LEEC. Nota: Não se permite a extensão do vector. }. v0. O campo currentSize não é estritamente necessário.2001/2002.

size()) x = 0.Classe CQueue – enqueue() e dequeue() template <class T>void CQueue<T>::enqueue(const T &x) { if (isFull()) throw Overflow(). return theArray[oldFront]. } Pilhas e Filas # 21 FEUP/LEEC. } template <class T> T CQueue<T>::dequeue() { if (isEmpty()) throw Underflow(). theArray[back] = x. increment(front).1 Notação RPN Notação RPN: Expressões aritméticas em que os operadores surgem a seguir aos operandos (notação pós-fixa). currentSize--. Notação infixa: 2 * ( 4 + 5 ) / 3 Notação RPN: 2 4 5 + * 3 / Vantagens de RPN: Não requer parênteses nem regras de precedência. v0. FEUP/LEEC. currentSize++.AED. } template <class T> void CQueue<T>::increment(int &x) { if (++x == theArray. int oldFront = front.AED. RPN=Reverse Polish Notation Notação infixa: Os operadores binários surgem entre os operandos.1 Pilhas e Filas # 22 11 . v0.2001/2002.2001/2002. increment(back).

(b) Se for um operador i. 2 4 5 + * 3 / 2 4 5 + * 3 / 2 4 5 + * 3 / 2 4 5 + * 3 / 2 4 5 + * 3 / 2 4 5 + * 3 / 2 4 5 + * 3 / 5 4 2 2 4 2 9 2 18 3 18 6 FEUP/LEEC. colocá-lo na pilha.3. Colocar o resultado na pilha. ii. Processar sequencialmente os elementos da expressão. iii. v0. Processar os elementos de acordo com o operador. Retirar os dois elementos do topo da pilha.3 de [DSAA]. Para cada elemento: (a) Se o elemento for um número.Avaliação de expressões RPN–Exemplo Uma expressão RPN é facilmente avaliada com a ajuda de uma pilha.1 Pilhas e Filas # 23 Avaliação de expressões RPN–Algoritmo 1. 2.2001/2002.AED. v0.2001/2002. (Ver tb.1 Pilhas e Filas # 24 12 . secção 3.AED.) FEUP/LEEC. Retirar o (único) elemento da pilha: é o resultado.

3. Os elementos da expressão são separados por espaços e terminadas com =. v0. Prioridades: ( / * + - FEUP/LEEC. v0. ^Z em Windows) FEUP/LEEC.1 Pilhas e Filas # 25 Conversão entre notação infixa e RPN A conversão entre notação infixa e RPN também pode ser feita com o recurso a uma pilha.AED. 4. Ler expressões de cin.AED. Quando surge um “)” esvazia-se a pilha até encontrar o primeiro “(“. Escrever os resultados em cout. Ignorar linhas vazias. Terminar com fim-de-ficheiro (^D em Unix. quando surge um operador todos os operadores de maior ou igual precedência são retirados da pilha.Especificação de um programa para avaliar expressões RPN 1. 5.2001/2002.2001/2002. 2. A pilha é usada para guardar os “operadores pendentes”.1 Pilhas e Filas # 26 13 .

3. ^Z em Windows) Os dois programas anteriores podem ser combinados em Unix: # i2r | postfix 2 * ( 3 + 4 ) . 2*(4+5)/3. 2*(4+5)/3 .1 Pilhas e Filas 14   Exemplo de conversão infixo RPN # 27 # 28 .AED. 4. 2*(4+5)/3. + ( * Saída: 2 4 5 * ( * ( * + ( * * + / * 3 / / = FEUP/LEEC. 14 ^D FEUP/LEEC. 2*(4+5) / 3. 2*(4+5)/3. v0. 5. terminados com =. 2. v0.2001/2002. Ignorar linhas vazias. Escrever os resultados em cout. 2*(4+5) / 3 .1 Pilhas e Filas Especificação do programa de conversão 1. 2*(4+5 ) / 3.AED. 2*(4+5)/3. 2*(4+5)/3. Ler expressões de cin.2*(4+5)/3.2001/2002. Terminar com fim-de-ficheiro (^D em Unix. Os elementos da expressão são separados por espaços e terminadas com ponto-e-vírgula.

Numerar todos os vizinhos do ponto inicial com 1.1 Pilhas e Filas # 29 Algoritmo de Lee 1. v0. 3.AED. Colocar os vizinhos numa fila. Enquanto a fila não estiver vazia e não se tiver atingido o ponto de destino: (a) Retirar um ponto da fila. 2. (b) Numerar os seus vizinhos livres com o número do ponto acrescido de 1.Percurso mais curto – Algoritmo de Lee Como encontrar o percurso mais curto entre dois pontos de um labirinto? 1 1 2 3 4 5 6 7 2 3 4 5 6 7 1 2 1 2 3 4 5 6 7 3 2 1 2 2 1 a 1 2 1 2 3 4 5 6 6 7 2 b 8 7 8 9 8 9 3 2 1 2 2 1 a 1 2 1 2 3 4 5 6 6 7 2 b 8 7 8 9 8 9 3 4 5 6 7 FEUP/LEEC. não existe percurso. Se a fila estiver vazia e não se tiver atingido o ponto de destino. FEUP/LEEC.AED. escrever o percurso em cout. Caso contrário.2001/2002. v0. (c) Colocar os novos pontos (vizinhos) na fila 4.2001/2002.1 Pilhas e Filas # 30 15 .

3. 2. Imprimir percurso em cout. v0.1) 1 1 1 1 1 1 0 0 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 0 0 0 0 0 1 1 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 (10. Fazer verificações de consistência.1 Pilhas e Filas # 31 Especificação do programa 1. 4. pontos inicial e final.2) 0 0 0 0 0 1 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 2 3 4 5 6 7 8 9 10 11 12 FEUP/LEEC. Aplicar algoritmo de Lee.2001/2002.AED.       zonas livres e ocupadas. Ler um ficheiro com: dimensão do labirinto.AED.2001/2002. FEUP/LEEC.1 Pilhas e Filas # 32 16 . v0.Especificação do labirinto 1 2 3 4 5 6 7 8 9 10 11 12 12 12 0 0 0 0 0 1 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 0 0 0 0 (1.

2001/2002. coluna. //. i++) { vizinho.Representação interna do labirinto 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0 0 0 1 1 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 2 3 4 5 6 7 1 2 3 4 5 6 7 FEUP/LEEC. -1 }.} }. int delta_linha[n_viz] = { 0. // Cálculo de vizinhança const int n_viz = 4. int delta_coluna[n_viz] = { 1. 0 }.2001/2002. i < n_viz. int col = 0) : linha(li).linha) && (coluna == pt. v0.... // .1 Pilhas e Filas # 33 Pontos e cálculo da vizinhança class Ponto { public: int linha. for (int i = 0. Pilhas e Filas # 34 FEUP/LEEC.AED.coluna). bool operator==(const Ponto &pt) const { return (linha == pt.coluna = corrente.linha = corrente. 0.1 17 . 0. v0.coluna + delta_coluna[i]. Ponto(int li = 0. vizinho. coluna(col) { }.linha + delta_linha[i].. 1.AED. -1.

AED. } corrente = vizinho.coluna = corrente. // encontrar predecessor for (int i = 0.coluna + delta_coluna[i]. vizinho.1 18 . i < n_viz.Determinação do percurso Ponto *percurso = new Ponto [comprimento_percurso]. j >= 0.2001/2002. for (int j = comprimento_percurso -1. v0. // refazer o percurso do ponto final para o inicial corrente = fim. j--) { percurso[j] = corrente. } Pilhas e Filas # 35 FEUP/LEEC.coluna] == j + 2) break.linha][vizinho. i++) { vizinho. if (grelha[vizinho.linha = corrente.linha + delta_linha[i].

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->