520 likes | 750 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
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
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 lista 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 lista processo: remove elemento do topo da pilha e atualiza pilha saida: endereço do elemento no topo da pilha ou NULL se pilha é vazia
TAD Pilha Top entrada: endereço da lista processo: consulta o topo da pilha saida: endereço do elemento no topo da pilha ou NULL se pilha é vazia
TAD Pilha Libera_pilha entrada: endereço da lista processo: libera toda area 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 sobre 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(struct stack)); if (Ptp != NULL) Ptp->topo = -1; return Ptp; }
Verifica se pilha é cheiaintE_cheia(Pilha Ptp) int E_cheia(Pilha Ptp) { if (Ptp->topo == MAX-1) return 1; else return 0; } intE_vazia(Pilha Ptp) int E_vazia(Pilha Ptp) { 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)->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* Pop(Pilha *Ptp) { int* elem; if ((*Ptp)->topo == -1) return NULL; elem = (int*)malloc(sizeof(int)); *elem = (*Ptp)->pilha[(*Ptp)->topo]; (*Ptp)->topo--; return elem; }
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* Top(Pilha Ptp) { int* elem; if (Ptp->topo == -1) return NULL; elem = (int*)malloc(sizeof(int)); *elem = Ptp->pilha[Ptp->topo]; return elem; } int* Top(Pilha Ptp) { if (Ptp->topo == -1) return NULL; return &(Ptp->pilha[Ptp->topo]); }
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* Top(Pilha Ptp); void Libera_pilha(Pilha *Ptp);
Exercício para entregar dia 17/06 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.
Pilhas Pilhas implementadas por encadeamento
remoções inserções ? consultas Topo Base Pilha implementada por encadeamento Endereço do topo da pilha PtPilha InfoElo Topo da pilha Tipo de dados utilizado nos algoritmos: struct no{ int info; struct no* elo; }; 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(struct no)); if (pt == NULL) return 0; pt->elo = (*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* Pop(Pilha* Ptp) { int* elem; Pilha aux = (*Ptp); if ((*Ptp) == NULL) return NULL; elem = (int*) malloc(sizeof(int)); *elem = (*Ptp)->info; (*Ptp)= (*Ptp)->elo; free(aux); return elem; }
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* Top(Pilha Ptp) { int* elem; if (Ptp == NULL) return NULL; elem = (int*) malloc(sizeof(int)); *elem = Ptp->info; return elem; }
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)->elo; 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 Proposta pelo lógico polones Jan lukasiewiscz em ? Permite escrever uma expressao aritmética em que a precedencia é implicita
Notação Polonesa 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 topo = desempilha coloca topo na expressaopos-fixa fim enquanto se (pilha eh vazia OU simbolo # ‘)’ ) empilha simbolo senao enquanto ( (topo = desempilha) != ‘(‘) coloca 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