CES11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Prticas

  • Slides: 57
Download presentation
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2016 Capítulo III Pilhas

CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2016 Capítulo III Pilhas

Objetivos do Lab 3: n Ler uma expressão na forma parentética; por exemplo, a

Objetivos do Lab 3: n Ler uma expressão na forma parentética; por exemplo, a expressão: tem a seguinte forma parentética: n Transformar, usando uma pilha, a parentética numa polonesa equivalente: ^ n Calcular, usando uma pilha, o valor da polonesa

Exercício 3. 1: Obtenção dos átomos de uma expressão aritmética parentética n Sejam expressões

Exercício 3. 1: Obtenção dos átomos de uma expressão aritmética parentética n Sejam expressões do tipo: (((x 1 + x 2) * (x 3 + (x 4 * x 5))) + x 6) também chamadas expressões na forma parentética onde xi é um número inteiro não negativo com um ou mais dígitos decimais, onde os operadores são somente “+” e “*”, e onde todas as operações são colocadas entre parênteses n Átomos de uma expressão como essas são os seus números, seus operadores e seus parêntesis

n Um átomo é uma entidade contendo dois campos: o tipo e um eventual

n Um átomo é uma entidade contendo dois campos: o tipo e um eventual atributo n Um átomo pode ser de um dos seguintes tipos: - NUM (abrev. de número): quando ele for um número inteiro OPER (abrev. de operador): quando ele for um dos caracteres ‘+’ ou ‘*’ ABPAR (abrev. de abre-parêntesis): quando ele for o caractere ‘(’ FPAR (abrev. de fecha-parêntesis): quando ele for o caractere ‘)’ INVAL (abrev. de átomo inválido): quando ele for qualquer outro caractere

n O eventual atributo de um átomo depende de seu tipo: - n NUM:

n O eventual atributo de um átomo depende de seu tipo: - n NUM: o atributo é o valor numérico do número OPER: o atributo é o próprio caractere ‘+’ ou ‘*’ ABPAR: o átomo não precisa de atributo FPAR: o átomo também não precisa de atributo INVAL: o atributo é o próprio caractere Tarefa: completar o esqueleto de programa a seguir que: - Lê uma expressão na forma parentética Encontra seus átomos (tipos e atributos), guardando-os numa lista de átomos (vetor de

n Exemplo: os átomos da expressão (13 * (45 + 7) &) serão guardados

n Exemplo: os átomos da expressão (13 * (45 + 7) &) serão guardados na seguinte lista de átomos denominada Parentetica: Vetor ABPAR 0 NUM OPER 13 * 1 2 ABPAR 3 NUM OPER NUM 45 + 7 4 5 6 natom FPAR INVAL FPAR & 7 8 9 10 Parentetica n O campo para o atributo de um átomo deverá ser uma union n A seguir, o esqueleto de programa

/* Inclusao de bibliotecas de C #include */ <stdio. h> <stdlib. h> <conio. h>

/* Inclusao de bibliotecas de C #include */ <stdio. h> <stdlib. h> <conio. h> <ctype. h> /* Declaracoes para o tipo logic */ typedef char logic; const logic TRUE = 1, FALSE = 0; /* Definicao dos tipos de atomos #define #define NUM OPER ABPAR FPAR INVAL 1 2 3 4 5 */ A serem usadas nos próximos exercícios

/* Declaracoes de tipos para as expressoes e listas de atomos */ typedef char

/* Declaracoes de tipos para as expressoes e listas de atomos */ typedef char expressao[50]; Campo valor: Para átomos do tipo NUM typedef union atribatomo; Campo carac: union atribatomo { Para átomos de tipos OPER int valor; char carac; e INVAL }; typedef struct atomo; struct atomo { int tipo; atribatomo atrib; }; typedef struct listaatomos; struct listaatomos { int natom; atomo Vetor[50]; }; tipo atrib O tipo atomo

/* Variaveis globais */ int i; char c; expressao Expr; listaatomos Parentetica; /* Prototipos

/* Variaveis globais */ int i; char c; expressao Expr; listaatomos Parentetica; /* Prototipos das funcoes auxiliares */ void char void Armazenar. Parentetica (void); Escrever. Lista. Atomos (listaatomos *); Prox. Nao. Branco (void); Armazenar. Parentetica: armazena os Prox. Carac (void); átomos de Expr na variável global Parentetica Inic. Expr (void); Podem ser escritas outras funções caso sejam convenientes Escrever. Lista. Atomos: escreve todos os átomos de uma lista de átomos Haverá mais uma lista além da Parentetica O argumento é passado por referência

/* Funcao main */ int main() { char c; printf ("Armazenar expressao parentetica? (s/n):

/* Funcao main */ int main() { char c; printf ("Armazenar expressao parentetica? (s/n): "); do c = getche (); while (c!='s' && c!='n' && c!='S' && c!='N'); while (c == 's' || c == 'S') { printf ("nn"); printf ("Digite a expressao: "); setbuf (stdin, NULL); gets (Expr); Armazenar. Parentetica (); Escrever. Lista. Atomos (&Parentetica); printf ("nn. Armazenar expressao parentetica? (s/n): "); do c = getche (); while (c!='s' && c!='n' && c!='S' && c!='N'); } printf ("nn"); printf ("Fim das atividades!"); printf ("nn"); system ("pause"); return 0; }

void Armazenar. Parentetica () { Zerar o número de átomos de Parentetica; Posicionar o

void Armazenar. Parentetica () { Zerar o número de átomos de Parentetica; Posicionar o cursor de Expr em seu início; Capturar o primeiro caractere não-branco; Enquanto ele não for o ‘’ { Preparar para formar um novo átomo; Se o caractere for um dígito { Coletar os outros dígitos; O tipo do átomo é NUM; O atributo é o valor numérico da cadeia formada pelos dígitos coletados; } Se for '+' ou '*' { O tipo do átomo é OPER; O atributo é o próprio caractere; } Diretrizes para a função Armazenar. Parentetica

} } Se for '(' ou ')' { O tipo do átomo é ABPAR

} } Se for '(' ou ')' { O tipo do átomo é ABPAR ou FPAR; O atributo não é necessário; } Se for qualquer outro caractere { O tipo do átomo é INVAL; O atributo é o próprio caractere; } Armazenar o átomo no final de Parentetica; Acrescentar uma unidade ao número de átomos de Parentetica; Capturar o próximo caractere não-branco; /* Fim do Enquanto */ /* Fim da função Armazenar. Parentetica */ Cuidado com os comandos para percorrer Expr Diretrizes para a função Armazenar. Parentetica

Diretrizes para a função Escrever. Lista. Atomos: Para uma expressão tal como ((12+32)*13 &

Diretrizes para a função Escrever. Lista. Atomos: Para uma expressão tal como ((12+32)*13 & + 43; )) a função deverá mostrar no vídeo uma tabela semelhante à seguinte: TIPO | ATRIBUTO ----------ABPAR | NUM | 12 OPER | + NUM | 32 FPAR | OPER | * NUM | 13 INVAL | & OPER | + NUM | 43 INVAL | ; FPAR |

/* Funcoes para percorrer a expressao */ char Prox. Nao. Branco () { while

/* Funcoes para percorrer a expressao */ char Prox. Nao. Branco () { while (isspace (Expr[i]) || (iscntrl (Expr[i]) && Expr[i] != '')) i++; return Expr[i]; } char Prox. Carac () { i++; return Expr[i]; } void Inic. Expr () { i = 0; }

Exercício 3. 2: Verificar se uma sequência de átomos é uma forma parentética correta

Exercício 3. 2: Verificar se uma sequência de átomos é uma forma parentética correta n A forma parentética de uma expressão pode ser definida recursivamente da seguinte maneira: 1. Sendo m e n dois números inteiros não negativos com um ou mais dígitos cada, (m + n) e (m * n) são expressões na forma parentética 2. Sendo α e β números inteiros não negativos ou expressões na forma parentética, (α + β) e (α * β) também são expressões na forma parentética n É necessário adaptar essa definição a expressões compostas de átomos, conforme definido no exercício anterior

Seja forma parentética definida para expressões em que os números são formados por apenas

Seja forma parentética definida para expressões em que os números são formados por apenas um dígito n A forma parentética de uma expressão pode ser definida recursivamente da seguinte maneira: 1. Sendo m e n dois dígitos quaisquer, (m + n) e (m * n) são expressões na forma parentética 2. Sendo α e β dígitos ou expressões na forma parentética, (α + β) e (α * β) também são expressões na forma parentética n Neste caso, a programação para checar se a expressão é uma forma parentética pode ser

/* Funcao Parentetica. Correta */ logic Parentetica. Correta () { logic r; i =

/* Funcao Parentetica. Correta */ logic Parentetica. Correta () { logic r; i = 0; r = Teste. Recursivo(); if (Expr[i] != '') r = FALSE; return r; }

/* Funcao Teste. Recursivo */ logic Teste. Recursivo () { logic r = TRUE;

/* Funcao Teste. Recursivo */ logic Teste. Recursivo () { logic r = TRUE; if (Expr[i] == '(') { i++; if (isdigit (Expr[i])) i++; else if (Expr[i] == '(') r = Teste. Recursivo (); else r = FALSE; if (r && (Expr[i] == '+' || Expr[i] == '*')) i++; else r = FALSE; if (r && isdigit (Expr[i])) i++; else if (r && Expr[i] == '(') r = Teste. Recursivo (); Estas funções podem servir de else r = FALSE; if (r && Expr[i] == ')') i++; guias para expressões compostas de átomos e para átomos else r = FALSE; numéricos contendo mais de um } dígito else r = FALSE; return r; }

Exercício 3. 3: Formar a polonesa correspondente à parentética armazenada n Conforme exercício resolvido

Exercício 3. 3: Formar a polonesa correspondente à parentética armazenada n Conforme exercício resolvido em aula teórica, a parentética (((x 1 + x 2) * (x 3 + (x 4 * x 5))) + x 6) pode ser colocada na forma polonesa sufixa, ou simplesmente polonesa, caracterizada pela transformação: x 1 x 2 + x 3 x 4 x 5 * + * x 6 + n Obter uma lista de átomos correspondente à

Método de transformação: n Percorrer o vetor da parentética n Ao encontrar um número,

Método de transformação: n Percorrer o vetor da parentética n Ao encontrar um número, inseri-lo no final da polonesa n Ao encontrar um operador, colocá-lo numa pilha de átomos n Ao encontrar um abre-parêntesis, nada fazer n Ao encontrar um fecha-parêntesis, desempilhar um operador e colocá-lo no final da polonesa

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 + Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 + Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 * + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 * + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + * Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + * 42 + Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + * 42 + Pilha de operadores

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42)

n Simulação: Parentética (((23 + 90) * (8 + (53 * 12))) + 42) Polonesa 23 90 + 8 53 12 * + * 42 + Polonesa formada ! Pilha de operadores

n Declarações e protótipos para o TAD Pilha (estrutura encadeada): typedef struct noh; typedef

n Declarações e protótipos para o TAD Pilha (estrutura encadeada): typedef struct noh; typedef noh *pilha; struct noh {atomo elem; noh *prox; }; void Empilhar (atomo, pilha*); void Desempilhar (pilha*); atomo Topo (pilha); void Inic. Pilha (pilha*); logic Vazia (pilha); Os elementos da pilha são átomos

n Funções-operadoras para o TAD Pilha (encadeada): void Empilhar (atomo x, pilha *P) {

n Funções-operadoras para o TAD Pilha (encadeada): void Empilhar (atomo x, pilha *P) { noh *temp; temp = *P; *P = (noh *) malloc (sizeof (noh)); (*P)->elem = x; (*P)->prox = temp; } void Desempilhar (pilha *P) { noh *temp; if (! Vazia(*P)) {temp = *P; *P = (*P)->prox; free (temp); } } atomo Topo (pilha P) {if (! Vazia(P)) return P->elem; } void Inic. Pilha (pilha *P) { *P = NULL; } logic Vazia (pilha P) { if (P == NULL) return TRUE; else return FALSE; }

Exercício 3. 4: Cálculo de expressões em polonesa n Foi visto que, para se

Exercício 3. 4: Cálculo de expressões em polonesa n Foi visto que, para se calcular o valor de uma expressão em polonesa, pode-se utilizar uma pilha: - n Percorre-se o vetor da polonesa Ao encontrar um número, deve-se colocá-lo na pilha Ao encontrar um operador, desempilha-se dois números, realiza-se a operação e empilha-se o resultado Não é necessário testar a polonesa, uma vez que ela é construída a partir de uma parentética correta

Exercício 3. 5: Extensão para operandos reais n Estender o programa do Exercício 3.

Exercício 3. 5: Extensão para operandos reais n Estender o programa do Exercício 3. 4 para trabalhar com números reais - Aceitar como número uma string que comece com um ou mais dígitos, seguidos opcionalmente por um ponto e zero ou mais dígitos - Exemplos: 127 56. 98. 75 0. 002 Exercício 3. 6: Extensão do programa do Exercício 3. 5 para os operadores binários de subtração ‘-’ e divisão ‘/’

Exercício 3. 7: Estender o programa do Exercício 3. 6 para trabalhar com os

Exercício 3. 7: Estender o programa do Exercício 3. 6 para trabalhar com os seguintes operadores: ~: menos unário L: logaritmo quadrada Exemplos de expressões parentéticas e polonesas usando esses operadores: ^: potenciação R: raiz