A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2017

Apresentações semelhantes


Apresentação em tema: "CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2017"— Transcrição da apresentação:

1 CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2017
Capítulo IV Árvores Binárias

2 O programa a ser desenvolvido neste capítulo irá:
Montar a árvore binária para uma expressão aritmética Calcular o valor dessa expressão, percorrendo sua árvore em profundidade

3 Exemplo:

4 O programa terá os seguintes passos principais:
A expressão será digitada numa forma parentética apropriada A forma parentética será convertida em polonesa A polonesa será percorrida do final ao início, para a construção da árvore binária correspondente A árvore binária será percorrida para o cálculo de seu valor

5 Exemplo simples: Digitação da expressão em forma parentética: ((( ) * (8 + (53 * 12))) + 42) Conversão de parentética para polonesa: * + *

6 Construção da árvore binária a partir da polonesa:
* + * +

7 Construção da árvore binária a partir da polonesa:
* + * + 42

8 Construção da árvore binária a partir da polonesa:
* + * + * 42

9 Construção da árvore binária a partir da polonesa:
* + * + * 42 +

10 Construção da árvore binária a partir da polonesa:
* + * + * 42 + *

11 Construção da árvore binária a partir da polonesa:
* + * + * 42 + * 12

12 Construção da árvore binária a partir da polonesa:
* + * + * 42 + * 53 12

13 Construção da árvore binária a partir da polonesa:
* + * + * 42 + 8 * 53 12

14 Construção da árvore binária a partir da polonesa:
* + * + * 42 + + 8 * 53 12

15 Construção da árvore binária a partir da polonesa:
* + * + * 42 + + 90 8 * 53 12

16 Construção da árvore binária a partir da polonesa:
* + * + * 42 + + 23 90 8 * 53 12

17 Cálculo do valor da expressão na árvore binária:
int ValExpressao (arvbin A) { caso a raiz de A seja: { número: retornar o valor do número; operador: caso o operador seja: { ‘+’: retornar ValExpressao (A->fesq) + ValExpressao (A->fdir); ‘*’: retornar ValExpressao (A->fesq) * }

18 (((n1 + n2) * (n3 + (n4 * n5))) + n6)
Exercício 4.1: Obtenção dos átomos de uma expressão aritmética Sejam expressões do tipo: (((n1 + n2) * (n3 + (n4 * n5))) + n6) também chamadas expressões na forma parentética, onde ni é um número inteiro não negativo com um ou mais dígitos decimais os operadores são somente ‘+’ e ‘*’ todas as operações são colocadas entre parênteses

19 (((n1 + n2) * (n3 + (n4 * n5))) + n6)
Átomos de uma expressão como essas são os seus números, seus operadores e seus parêntesis. Um átomo é uma entidade contendo dois campos: o tipo e um eventual atributo. Um átomo pode ser de um dos seguintes tipos: NUMERO: quando ele for um número inteiro OPERADOR: quando ele for um dos caracteres ‘+’ ou ‘*’ ABPAR: quando ele for o caractere ‘(’ FPAR: quando ele for o caractere ‘)’ INVAL: quando ele for qualquer outro caractere

20 (((n1 + n2) * (n3 + (n4 * n5))) + n6)
O eventual atributo de um átomo depende de seu tipo: NUMERO: o atributo é o valor numérico do número OPERADOR: 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 Declarações para átomos: typedef struct atomo atomo; typedef union atribatomo atribatomo; union atribatomo { int valor; char oper, carac;}; struct atomo { int tipo; atribatomo atrib;};

21 Exemplo: átomos da expressão ((35 + 62) * 7)
tipo ABPAR atrib tipo ABPAR atrib tipo NUMERO atrib / valor 35 tipo OPERADOR atrib / oper + tipo NUMERO atrib / valor 62 tipo FPAR atrib tipo OPERADOR atrib / oper * tipo NUMERO atrib / valor 7 tipo FPAR atrib typedef struct atomo atomo; typedef union atribatomo atribatomo; union atribatomo { int valor; char oper, carac;}; struct atomo { int tipo; atribatomo atrib;};

22 Trabalho a fazer: completar o esqueleto de programa a seguir que:
Lê uma expressão na forma parentética Encontra seus átomos (tipos e atributos), guardando-os num vetor de átomos Escreve no vídeo o conteúdo desse vetor.

23 /* Biblioteca utilizada da linguagem */
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <ctype.h> /* Constantes simbolicas gerais */ #define logic char #define TRUE 1 #define FALSE 0 /* Constantes simbolicas para os tipos dos atomos */ #define NUMERO 1 #define OPERADOR 2 #define ABPAR 3 #define FPAR 4 #define INVAL 5

24 Parentetica: vetor de átomos para armazenar os átomos da expressão
/* Declaracoes de tipos */ typedef char expressao[100]; typedef struct atomo atomo; typedef union atribatomo atribatomo; union atribatomo {int valor; char oper, carac;}; struct atomo {int tipo; atribatomo atrib;}; /* Variaveis globais */ atomo Parentetica[100]; int nparent, i; char c; expressao expr; Parentetica: vetor de átomos para armazenar os átomos da expressão nparent: número atual de átomos em Parentetica expr: vetor de caracteres com a expressão i: cursor para percorrer expr c: guarda um caractere de expr

25 GetNonBlank: procura o próximo caractere não-branco em expr
/* Prototipos das funcoes auxiliares */ void FormarAtomos (void); void EscreverAtomos (int, atomo[]); char GetNonBlank (void); char GetNext (void); void InicExpr (void); FormarAtomos: encontra todos os átomos de expr e os armazena em Parentetica EscreverAtomos: escreve na tela o conteúdo de todos os átomos em um vetor de átomos GetNonBlank: procura o próximo caractere não-branco em expr GetNext: retorna o próximo caractere de expr InicExpr: posiciona o cursor i no primeiro caractere de expr

26 /* Funcao main */ int main() { char c; printf ("Encontrar atomos de expressao? (s/n): "); do c = getche ( ); while (c!='s' && c!='n' && c!='S' && c!='N'); while (c == 's' || c == 'S') { clrscr (); printf ("Digite a expressao: "); setbuf (stdin, NULL); gets (expr); FormarAtomos (); printf ("\nAtomos da expressao:\n"); EscreverAtomos (nparent, Parentetica); printf ("\n\nEncontrar atomos de nova expressao? (s/n): "); } clrscr (); printf ("Fim das atividades!"); printf ("\n\n"); system ("pause"); return 0;

27 A função FormarAtomos poderá seguir as seguintes diretrizes:
void FormarAtomos () { Zerar o número de átomos encontrados; Posicionar o cursor da expressão em seu início; Procurar o primeiro caractere não branco; enquanto esse caractere não for o ‘\0’ { Inserir um novo átomo em Parentetica, conforme o valor desse caractere; Caso seja dígito { } Caso seja '+' ou '*' { } Caso seja '(' ou ')' { } Caso seja qualquer outro caractere { } Acrescentar uma unidade ao número de átomos encontrados; Procurar o próximo caractere não branco; }

28 Caso seja dígito { Coletar os outros dígitos; O tipo do átomo é NUMERO; O atributo é o valor numérico da cadeia formada pelos dígitos coletados; } Caso seja '+' ou '*' { O tipo do átomo é OPERADOR; O atributo é o próprio caractere; Caso seja '(' ou ')' { O tipo do átomo é respectivamente ABPAR ou FPAR; O atributo não é necessário; Caso seja qualquer outro caractere { O tipo do átomo é INVAL;

29 Para uma expressão tal como
( ( )*13 & + 43;) ) a função EscreverAtomos deverá mostrar na tela uma tabela semelhante à seguinte: Atomos da expressao: TIPO | ATRIBUTO ABPAR | NUMERO | 12 OPERADOR | + NUMERO | 32 FPAR | OPERADOR | * NUMERO | 13 INVAL | & NUMERO | 43 INVAL | ;

30 /* Funcoes para percorrer a expressao */
char GetNonBlank ( ) { while (isspace (expr[i]) || (iscntrl (expr[i]) && expr[i] != '\0')) i++; return expr[i]; } char GetNext () { i++; void InicExpr ( ) { i = 0;

31 Exercício 4.2: Verificar se um vetor de átomos guarda a forma parentética de uma expressão, usando a seguinte definição recursiva: 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. Sendo α e β números inteiros não negativos ou expressões na forma parentética, (α + β) e (α * β) também são expressões nessa forma. É necessário adaptar essa definição a expressões compostas de átomos, conforme definido no exercício anterior.

32 Exercício 4.3: Transformar parentética em polonesa
Obter um vetor de átomos correspondente à polonesa de uma expressão guardada num vetor de átomos, na forma parentética Exemplo: seja a seguinte forma parentética: ((( ) * (8 + (53 * 12))) + 42) Sua polonesa correspondente: * + *

33 Método de transformação:
Percorrer o vetor da parentética; Ao encontrar um número, inseri-lo no final da polonesa Ao encontrar um operador, colocá-lo numa pilha de átomos; Ao encontrar um abre-parêntesis, nada fazer; Ao encontrar um fecha parêntesis, desempilhar um operador e colocá-lo no final da polonesa Sugestão: montar a polonesa durante o teste da parentética (Exercício 4.2)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

55 Declarações e protótipos para o TAD Pilha (estrutura encadeada):
typedef struct noh noh; typedef noh *pilha; struct noh {atomo elem; noh *prox;}; void Empilhar (atomo, pilha*); void Desempilhar (pilha*); atomo Topo (pilha); void InicPilha (pilha*); logic Vazia (pilha);

56 Funções-operadores para o TAD Pilha (estrutura 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 InicPilha (pilha *P) { *P = NULL; } logic Vazia (pilha P) { if (P == NULL) return TRUE; else return FALSE; }

57 Exercício 4.4: Construir uma árvore binária para a expressão, a partir da polonesa
Exemplo: Polonesa * + * 42 + Árvore binária

58 Declarações para árvore binária:
typedef struct celula celula; typedef celula *noharvbin; typedef celula *arvbin; struct celula {atomo elem; celula *pai, *fesq, *fdir;}; arvbin Arv; elem (atomo) pai fesq fdir celula Arv Árvore binária

59 Exercício 4.5: Escrever a forma parentética original da expressão, a partir da árvore binária
Diretriz: percorrer a árvore binária em ordem-central, escrevendo os atributos dos nós e escrevendo parêntesis em momentos oportunos

60 Exercício 4.6: Calculo do valor da expressão na árvore binária:
Diretrizes: int ValExpressao (arvbin A) { caso a raiz de A seja: { número: retornar o valor do número; operador: caso o operador seja: { ‘+’: retornar ValExpressao (A->fesq) + ValExpressao (A->fdir); ‘*’: retornar ValExpressao (A->fesq) * }

61 Exercício 4. 7: Estender o programa do Exercício 4
Exercício 4.7: Estender o programa do Exercício 4.6 para trabalhar com números reais Aceitar como número uma cadeia que comece com um ou mais dígitos, seguidos opcionalmente por um ponto e zero ou mais dígitos Exercício 4.8: Estender o programa do Exercício 4.7 para trabalhar com os operadores binários ‘-’ (subtração) e ‘/’ (divisão)

62 Exercício 4. 9: Estender o programa do Exercício 4
Exercício 4.9: Estender o programa do Exercício 4.8 para trabalhar com os seguintes operadores: ~: menos unário @: potenciação L: logaritmo R: raiz quadrada S: seno C: cosseno

63 Exemplos de expressões parentéticas e polonesas usando esses operadores:


Carregar ppt "CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2017"

Apresentações semelhantes


Anúncios Google