580 likes | 983 Views
Pilhas e Filas. Denise Guliato Faculdade de Computação – UFU www.facom.ufu.br/~guliato. Vários slides foram adaptados de Nina Edelwais e Renata Galante Estrutura de Dados – Série de Livros Didáticos - Informática - UFRGS. Pilhas e filas. Listas lineares especiais.
E N D
Pilhas e Filas Denise Guliato Faculdade de Computação – UFU www.facom.ufu.br/~guliato Vários slides foram adaptados de Nina Edelwais e Renata Galante Estrutura de Dados – Série de Livros Didáticos - Informática - UFRGS
Pilhas e filas Listas lineares especiais Com disciplina restrita de organização e acesso a seus nodos • Disciplina restrita • acesso permitido somente em alguns nodos
Pilhas e filas Listas lineares especiais mais usuais LIFOLast In First Out o último componente inserido é o primeiro a ser retirado FIFO First In First Out o primeiro componente inserido é também o primeiro a ser retirado Pilha Fila
Pilhas e Filas Exclusões Inserções Consultas Topo PILHA Base FILA Final Início Exclusões e Consultas Inserções
Pilhas Exclusões Inserções Consultas Topo Base Operações sobre Pilhas • Criar uma pilha vazia • Inserir um elemento no topo da pilha • Remover um elemento do topo de pilha • Consultar o topo da pilha • Destruir a pilha • Verificar se é cheia • Verificar se é vazia
TAD Pilha Dados: numeros inteiros Operações: E_cheia entrada: o endereço da pilha processo: verifica se pilha esta na condição de cheia saida: 1 se cheia, 0 caso contrário (-1 se pilha não existe)
TAD Pilha E_vazia entrada: endereço da pilha processo: verifica se a pilha está na condição de vazia saida: 1 se vazia, 0 caso contrario (-1 se a pilha não existe)
TAD Pilha Cria_pilha entrada: nenhuma processo: aloca a pilha e a coloca na condição de vazia saida: endereço da pilha
TAD Pilha Push entrada: endereço da variável que contém o endereço da pilha e o elemento processo: insere elemento no topo da pilha e atualiza pilha saida: 1 se sucesso , 0 se fracasso
TAD Pilha Pop entrada: endereço da variavel que contem o endereço da pilha e endereço do elemento que conterá o valor do elemento a ser removido processo: remove elemento do topo da pilha e atualiza pilha saida: 1 se sucesso e 0 se fracasso
TAD Pilha Top entrada: endereço da pilha e o endereço do elemento consultado processo: consulta o topo da pilha saida: 1 se sucesso e 0 se fracasso
TAD Pilha Libera_pilha entrada: endereço do endereço da pilha processo: libera toda área alocada para a pilha saida: nenhuma
Pilhas Pilhas implementadas por contiguidade física
Pilha – contiguidade física LIMITE Topo Base Pilha Pilha - contiguidade física • Implementada usando umarranjo • Índices de controle da pilha: • BASE da pilha • TOPOatual da pilha • LIMITE máximo que pode ser ocupado pela pilha Índices do arranjo
Pilha – contiguidade física Exemplo de manipulação de uma pilha 1. Inicializar pilha de valores inteiros,a partir do índice 0, máximo 10 nós 2. Inserir nodo com valor 3 3. Inserir nodo com valor 7 4. Inserir nodo com valor 5 5. Remover nodo do topo 6. Consultar pilha Retorna “5” Retorna “7” 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 MAX-1 MAX-1 MAX-1 MAX-1 MAX-1 9 8 7 6 5 4 3 2 1 0 5 TOPO 7 7 7 TOPO TOPO BASE BASE BASE BASE BASE 3 3 3 3 TOPO TOPO PILHA PILHA PILHA PILHA PILHA
Pilha – contiguidade física Tipo de dados utilizado nos algoritmos para pilha implementada por contiguidade física: struct stack { int pilha[MAX]; int topo; }; typedef struct stack Pilha;
Pilha – contiguidade física Criação da pilha 9 8 7 6 5 4 3 2 1 0 MAX - 1 1. Alocar área para a pilha 2. Indicar que a pilha está vazia Exemplo: Base Base 0 Topo – 1 MAX 10 Topo Pilha
Pilha – contiguidade física Algoritmo:criação de umapilha Pilha *Cria_pilha(void) Pilha *Cria_pilha(void) { Pilha *Ptp; Ptp = (Pilha*) malloc(sizeof(Pilha)); if (Ptp != NULL) Ptp->topo = -1; return Ptp; }
Verifica se pilha é cheiaintE_cheia(Pilha *Ptp) int E_cheia(Pilha *Ptp) { if ( Ptp == NULL) return -1; if (Ptp->topo == MAX-1) return 1; else return 0; } intE_vazia(Pilha *Ptp) int E_vazia(Pilha *Ptp) { if (Ptp == NULL) return -1; if (Ptp->topo == -1) return 1; else return 0; }
Pilha – contiguidade física Inserção de um elemento napilha Operação PUSH 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 MAX - 1 MAX -1 Topo Topo Base Base Pilha Pilha
Pilha – contiguidade física Algoritmo: inserer elemento no topo da pilha intPush(Pilha **Ptp, int elem) int Push(Pilha **Ptp, int elem) { if ((*Ptp) == NULL||(*Ptp)->topo == MAX-1) return 0; (*Ptp)->topo++; (*Ptp)->pilha[(*Ptp)->topo] = elem; return 1; }
Pilha – contiguidade física MAX - 1 Topo Base Pilha Remoção de um elemento da pilha Operação POP 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 MAX - 1 Topo Base Pilha
Algoritmo:Remover elemento do topo de Pilha int Pop(Pilha **Ptp, int *elem) int Pop(Pilha **Ptp, int *elem) { if ((*Ptp) == NULL || (*Ptp)->topo == -1) return 0; *elem = (*Ptp)->pilha[(*Ptp)->topo]; (*Ptp)->topo--; return 1; }
Pilha – contiguidade física Consulta o topa da pilha 9 8 7 6 5 4 3 2 1 0 MAX - 1 • Acesso somente ao elemento do topo da pilha ? Topo Base Pilha
Algoritmo:Consultar o elemento do topo de Pilha int Top(Pilha *Ptp, int *elem) int Top(Pilha *Ptp, int *elem) { if (Ptp == NULL || Ptp->topo == -1) return 0; *elem = Ptp->pilha[Ptp->topo]; return 1; }
Destruição da pilhavoidLibera_pilha(Pilha** Ptp) void Libera_pilha(Pilha **Ptp) { free(*Ptp); *Ptp=NULL; }
paeas.h typedef struct stack Pilha; int E_cheia(Pilha *Ptp); int E_vazia(Pilha *Ptp); Pilha *Cria_pilha(void); int Push(Pilha **Ptp, int elem); int Pop(Pilha **Ptp, int *elem); Int Top(Pilha *Ptp, int *elem); void Libera_pilha(Pilha **Ptp);
Exercício para entregar agora Implemente o TAD utilizando uma estrutura de dados com alocação estática e acesso sequencial Implemente uma função que, usando o TAD Pilha, verifique se uma dada palavra representada como uma STRING (que não contenha brancos) é uma palíndromo (palavras que não se alteram quando lidas da direita para a esquerda ou da esquerda para a direita). ReExemplos: ANA, ADGHGDA. Retorne 1 se palavra é palindromo, e 0 caso contrario. Faça um programa que leia uma string (conjunto de palavras separadas por brancos) e indique quais palavras da string são palindromos e quais não são. A string eh dada por linha de comando
Pilhas Pilhas implementadas por encadeamento
remoções inserções ? consultas Topo Base Pilha implementada por encadeamento Endereço do topo da pilha PtPilha Info prox Topo da pilha Tipo de dados utilizado nos algoritmos: struct no{ int info; struct no* prox; }; typedef struct no Pilha; Base da pilha
Pilha por encadeamento Criação de pilha encadeada • Pilha criada vazia • Atribuir endereço nulo para apontador que contém o endereço do topo da pilha
Pilha por encadeamento Algoritmo:Criar PilhaEncadeada Pilha* Cria_pilha(void) Pilha* Cria_pilha(void) { return NULL; }
Pilha por encadeamento Inserção de um nodo em pilha encadeada • Novo nodo inserido sempre no topo da pilha PtPilha PtPilha Topo Novo nodo Topo Topo Base Base
Pilha por encadeamento Algoritmo: Inserir nodo emPilhaEncadeada intPush(Pilha **Ptp, int elem) int Push(Pilha **Ptp, int elem) { Pilha *pt; pt= (Pilha*)malloc(sizeof(Pilha)); if (pt == NULL) return 0; pt->prox = (*Ptp); pt->info = elem; (*Ptp) = pt; return 1; }
Pilha por encadeamento Desempilhaum nodo de uma pilha encadeada • Só pode ser removido o nodo do topo da pilha Nodo a ser removido PtPilha PtPilha Topo Topo Base Base
Pilha por encadeamento Algoritmo: Desempilha nodo de PilhaEncadeada int Pop(Pilha * *Ptp, int* elem) int Pop(Pilha **Ptp, int *elem) { Pilha *aux = *Ptp; if (*Ptp == NULL) return 0; *elem = (*Ptp)->info; *Ptp= (*Ptp)->prox; free(aux); return 1; }
Pilha por encadeamento Consulta à pilha encadeada • Só pode ser acessado o nodo do topo da pilha Nodo que pode ser acessado PtPilha Topo Base
Pilha por encadeamento Algoritmo: Consultar nodo do topo de PilhaEncadeada int Top (Pilha *Ptp, int *elem) int Top(Pilha *Ptp, int *elem) { if (Ptp == NULL) return 0; *elem = Ptp->info; return 1; }
Pilha por encadeamento Destruição de uma pilha encadeada • Liberar espaço ocupado pelos nodos, sempre a partir do topo da pilha • No final: apontador para o topo = endereço nulo PtPilha Topo PtPilha Topo PtPilha Topo Topo Base Base Base Base PtPilha = nil
Pilha por encadeamento Algoritmo: Destruir PilhaEncadeada void Libera_pilha(Pilha **Ptp) void Libera_pilha(Pilha **Ptp) { Pilha *aux; while ((*Ptp) != NULL) { aux = (*Ptp); (*Ptp) = (*Ptp)->prox; free(aux); } }
Verifica de pilha esta cheiaint E_cheia(Pilha *Ptp) int E_cheia(Pilha *Ptp) { return 0; } Verifica de pilha esta vaziaintE_vazia(Pilha *Ptp) int E_vazia(Pilha *Ptp) { if (Ptp == NULL) return 1; else return 0; }
Exercício Implemente o TAD Pilha utilizando alocação dinâmica de memória e acesso encadeado. Teste o programa para reconhecer quais palavras são palíndromos em uma dada frase.
Aplicação da estrutura de dados Pilha em avaliação de expressões aritméticas Forma das expressões Considere: Operandos: [0,...,9] Operadores:[+,-,/,x,^] Delimitadores: [(,)] Exemplos: 2 + 3 * 5 = 17 (2 + 3) * 5 = 25 As operações são efetuadas de acordo com a ordem de precedência dos operadores; Os parênteses alteram a ordem natural de avaliação dos operadores.
Proponham um algoritmo para avaliar expressões aritméticas 22 – 56 / 2; (22-56)/2; 40/(2x(3-1) +6); 2^3x4; 2^(3x4); ?
Notação Polonesa e Notação Polonesa Inversa Notação Polonesa (pré-fixada)- Proposta pelo matemático Jan lukasiewiscz em 1920 permite escrever uma expressão aritmética em que a precedência é implícita Notação Polonesa Inversa (pós-fixada) - proposta por Charles Hamblin em 1950.
Notação Polonesa e Notação Polonesa Inversa forma pós-fixada 2 5 3 x + 2 3 + 4 - 2 3 4 - + 2 4 + 3 1 - / 2 4 + 3 1 – / 4 x 2 2 ^ 3 * 4 – 1 2 / 1 1 + / + forma pré-fixada + 2 x 5 3 - + 2 3 4 + 2 – 3 4 / + 2 4 -3 1 x / +2 4-3 1 4 + -*^2 2 3 4 / / 1 2 + 1 1 expressão: ---------- 2 + 5 x 3 2 + 3 – 4 2 + (3 – 4) (2 + 4)/(3 -1) (2+4)/(3-1)x4 2^2*3-4+1/2/(1+1)
Forma pós-fixada para avaliar expressoes aritmeticas usando pilha float avalia_expressao(char *pos-fixada) float avalia_expressao(char *pos-fixada) Inicio Ptp aponta para uma pilha vazia Enquanto (nao processou toda expressao pos-fixada) Inicio simbolo = token; se (simbolo é um operando) empilha simbolo na pilha Ptp senao inicio operando2 = desempilha elemento da pilha Ptp operando1 = desempilha elemento da pilha Ptp valor = operando1 simbolo operando2 empilha valor na pilha Ptp fim se Fim enquanto Retorna (desempilha o elemento da pilha Ptp) Fim da funçao
Como transformar uma expressão na forma infixa para pos-fixa??? • Expressões entre parênteses devem ser convertidos de tal forma que possam ser tratadas como um único operando. • Somente operadores são empilhados . Um operador é empilhado apenas se possui precedência maior que o operador no topo da pilha. • Abre parênteses é sempre empilhado • Fecha parênteses nunca é empilhado (menor precedência).Todos os operadores são desempilhados até encontrar um ‘(‘. • Operandos e operadores desempilhados são colocados na expressão na forma pós-fixa
Algoritmo: char* pos-fixa(char* in-fixa) Inicio inicializa pilha de operadores e aloca area do tamanho da expressao in-fixa enquanto (não processou toda a expressao in-fixa) inicio simbolo = token se (simbolo é operando) coloca simbolo na expressaopos-fixa senao inicio enquanto (pilha não eh vazia E precedencia(topo da pilha, simbolo) inicio elem-topo = desempilha coloca elem-topo na expressaopos-fixa fim enquanto se (pilha eh vazia OU simbolo # ‘)’ ) empilha simbolo senao enquanto ( (elem-topo = desempilha) != ‘(‘ ) coloca elem-topo na expressaopos-fixa; fim se fim se fim enquanto enquanto ( pilha não eh vazia) desempilha topo e coloca na expressaopos-fixafim enquanto Fim da função símbolo topo de pilha Precedencia(‘(‘, op) --- false Precedencia (op,’(‘) ---- false, exceto op=‘)’ Precedencia (op,’)’) -----false, exceto op=‘(‘ Precedencia (‘)’, op) --- indefinido Se precedência do topo da pilha maior que símbolo true