2. Tipos Abstratos de Dados



Documentos relacionados
Circuitos Aritméticos

Orientação a Objetos

Proporcionar a modelagem de sistemas utilizando todos os conceitos da orientação a objeto;

ÁLGEBRA BOOLEANA- LÓGICA DIGITAL

Linguagens e Paradigmas de Programação

Escola Secundária c/3º CEB José Macedo Fragateiro. Curso Profissional de Nível Secundário. Componente Técnica. Disciplina de

Requisitos de Software

Capítulo VI Circuitos Aritméticos

1.1. Definição do Problema

POTENCIAÇÃO, RADICIAÇÃO E LOGARITMAÇÂO NOS NÚMEROS REAIS. Potenciação 1

LINGUAGEM SQL Linguagem usada em SGBD para: Definir estrutura de dados; Modificar dados em um banco de dados; Especificar restrições de segurança; Rea

Algoritmos e Estruturas de Dados I. Variáveis Indexadas. Pedro O.S. Vaz de Melo

Ciclo com Contador : instrução for. for de variável := expressão to. expressão do instrução

Conceitos c++ Prof. Demétrios Coutinho INFORMÁTICA BÁSICA

Sistemas Distribuídos Capítulo 4 - Aula 5

Trabalho Prático II - Resta 1 Data de Entrega: Conferir no calendário!

INTRODUÇÃO À PROGRAMAÇÃO II VARIÁVEIS COMPOSTAS HOMOGÊNEAS UNIDIMENSIONAIS

Programação de Computadores I. Linguagem C Função

Processo de Desenvolvimento de Software

Sistema Operacional. Implementação de Processo e Threads. Prof. Dr. Márcio Andrey Teixeira Sistemas Operacionais

números decimais Inicialmente, as frações são apresentadas como partes de um todo. Por exemplo, teremos 2 de um bolo se dividirmos esse bolo

Aula 01 Introdução Custo de um algoritmo, Funções de complexidad e Recursão

Programação de Computadores - I. Profª Beatriz Profº Israel

números decimais Inicialmente, as frações são apresentadas como partes de um todo. Por exemplo, teremos 2 de um bolo se dividirmos esse bolo

Teste de Funções por Cobertura do Grafo de Fluxo de Controle

Os conceitos aprendidos são fundamentais, essenciais para escrever um programa macro. Mas o que é um programa macro?

AGRUPAMENTO DE ESCOLAS DR. VIEIRA DE CARVALHO

Professora Isabel Harb Manssour Paradigmas de Linguagens I 1

Tipos Abstratos de Dados (TAD)

Qualidade de Produto. Maria Cláudia F. P. Emer

03. [Sebesta, 2000] Descreva a operação de um gerador de linguagem geral.

- Campus Salto. Disciplina: Sistemas de Arquivos Docente: Fernando Santorsula

CURSO DE MATEMÁTICA BÁSICA PROGRAMA DE EDUCAÇÃO TUTORIAL CENTRO DE ENGENHARIA DA MOBILIDADE

Estruturas de Repetição

Curso de criação de componentes em Delphi

9. Tipos Abstratos de Dados

Módulo IV Programação Visual Basic. Programação

Comandos de Desvio 1

UNIPAC Araguari FACAE - Faculdade de Ciências Administrativas e Exatas SISTEMAS DE INFORMAÇÃO

Em cada uma dessas frases, há uma quantidade indicada em forma de fração. Veja:

Seqüências. George Darmiton da Cunha Cavalcanti CIn - UFPE

Introdução. Qualidade de Produto. Introdução. Introdução ISO/IEC Normas

Fundamentos de Arquitetura e Organização de Computadores

Potenciação e radiciação

Gerenciamento de Integração. Prof. Anderson Valadares

Montadores e Compiladores

EXERCÍCIOS PREPARATÓRIOS PARA AS DISCIPLINAS INTRODUTÓRIAS DA MATEMÁTICA

FRAÇÃO Definição e Operações

3. COMPILAÇÃO E ESTRUTURA BÁSICA DE UM PROGRAMA EM C

TUTORIAL MATLAB Victor Breder 2016

PLANO DE ENSINO DE MATEMÁTICA 1ª SÉRIE DO ENSINO MÉDIO 1º BIMESTRE DIRETORIA DE ENSINO REGIÃO CAIEIRAS

Árvores Parte 1. Aleardo Manacero Jr. DCCE/UNESP Grupo de Sistemas Paralelos e Distribuídos

Nº horas ESTRATÉGIAS RECURSOS AVALIAÇÃO

FRAÇÃO. Número de partes pintadas 3 e números de partes em foi dividida a figura 5

Algoritmos e Programação : Conceitos e estruturas básicas. Hudson Victoria Diniz

Arquitetura TCP/IP. Apresentado por: Ricardo Quintão

BANCO DE DADOS. Professor: André Dutton

Álgebra Linear AL. Luiza Amalia Pinto Cantão. Depto. de Engenharia Ambiental Universidade Estadual Paulista UNESP

Análise Léxica. Sumário

Algoritmos APRENDENDO A PROGRAMAR COM C#

Linguagens de Programação:

Determinantes. Matemática Prof. Mauricio José

BANCO DE DADOS I AULA 2. Willamys Araújo willamysaraujo7@gmail.com

Variáveis Frequências Gráficos Medidas de Posição Medidas de Dispersão Medidas Complementares Inferência

Análise de Sistemas de Controle no Espaço de Estados

Introdução a Funções

Método Simplex Revisado

Sistemas Digitais II. Interface com o mundo analógico. Prof. Marlon Henrique Teixeira Abril/2014

Usando potências de 10

7. Defina encapsulamento. R.: Encapsular é ocultar. Criar uma cápsula ao redor da classe, para proteger o que está dentro dela.

Definição de determinantes de primeira e segunda ordens. Seja A uma matriz quadrada. Representa-se o determinante de A por det(a) ou A.

Introdução à Programação. Funções e Procedimentos. Prof. José Honorato F. Nunes honoratonunes@gmail.com

Verificação e validação

Algoritmo e Pseudo-código

Padrões de Projeto. Factory Method

TAD: Tipo Abstrato de Dados (parte 1)

=...= 1,0 = 1,00 = 1,000...

AF Não-determinísticos Equivalência entre AFND e AFD

MANUAL DO USUÁRIO SIMPLEX. Prof. Erico Fagundes Anicet Lisboa, M. Sc.

OpenPDV: Sistema aberto para gerenciamento de restaurantes

Avaliação e Desempenho Aula 1 - Simulação

As operações de adição, subtração e multiplicação são feitas de maneira natural, considerando-se o número complexo como um binômio.

Aula 05 Instalação e Uso do Arcabouço. Alessandro Garcia Alexander Chávez LES/DI/PUC-Rio Março 2016

Unidade 3 Função Afim

Planificação de Unidade TEMA II Introdução ao Cálculo Diferencial I. Funções Racionais. Taxa de Variação e Derivada.

Compiladores II. Fabio Mascarenhas

Sistemas Digitais Ficha Prática Nº 7

Seleção de Materiais. 1. Introdução. 1. Introdução

Vírgula flutuante Aula 6

Vamos imaginar que queremos projetar um jogo em que haja diferentes personagens:

5 - Qual é a principal vantagem de desenvolvimento de código por pares:

Projetando um Computador

Java possui 4 tipos de dados. Estes tipos de dados são divididos em: boolean, character, integer e float.

Exercícios: Vetores e Matrizes

Objectos Gráficos 1. APROG (Civil) Aula 4. Friday, November 2, 12

Universidade dos Açores Curso de Especialização Tecnológica Gestão da Qualidade Matemática

Inversão de Matrizes

1 Teoria de conjuntos e lógica

Universidade Paulista

Introdução. Software Básico Aula 3. Prof. Dr. Rogério Vargas.

Transcrição:

2. Tipos Abstratos de Dados Um Tipo Abstrato de Dados especifica uma classe de dados definida pelo usuário em termos de suas propriedades abstratas Esta especificação do TAD descreve o comportamento de um objeto independentemente de sua implementação; unicamente através dessas propriedades abstratas Não há preocupação de como essas propriedades seriam implementadas numa linguagem de programação A forma usual de se especificar um tipo abstrato de dados é através de uma especificação algébrica, que em geral contém três partes: 1. Especificação sintática: define o nome do tipo, suas operações e o tipo dos argumentos das operações. Dizemos que define a assinatura ou interface do TAD 2. Especificação Semântica: contém um conjunto de equações algébricas, que descreve, independentemente de uma implementação específica, as propriedades das operações 3. Especificação das Restrições: estabelece as condições que devem ser satisfeitas antes e depois da aplicação das operações Vamos agora mostrar a especificação dos número naturais como um TAD. Definiremos os naturais Nat = {0, 1, 2, 3,...} com as operações teste de zero, soma e igualdade através da seguinte especificação 1 2 3 ABSTRACT Nat sintaxe zero() Nat IsZero(Nat) Boolean Succ(Nat) Nat 1

4 Add(Nat, Nat) Nat 5 Eq(Nat, Nat) Boolean 6 semantic x, y Nat 6 IsZero(Zero)= true 7 IsZero(Succ(x))= false 8 Add(Zero, y)= y 9 Add(Succ(x),y)= Succ(Add(x, y)) 10 Eq(x, Zero)= if IsZero(x) then true else false 11 Eq(Zero, Succ(y))= false 12 Eq(Succ(x),Succ(y))= Eq(x, y) 13 restrictions end Zero é a função constante que significa não precisar de argumento de entrada e o seu resultado é o número natural zero, escrito Zero IsZero é a função booleana cujo resultado será verdadeiro ou falso, conforme o número do tipo Nat passado como parâmetro seja zero ou não Succ significa o sucessor do número passado como parâmetro Usando Zero e Succ podemos definir todos os números naturais como: 0 = Zero 1 = Succ(Zero) 2 = Succ(Succ(Zero)) 3 = Succ(Succ(Succ(Zero)))... As regras das linhas 8 e 9 nos mostram exatamente como funciona a operação de adição. Por exemplo, se queremos somar 2 com 3 teremos a seguinte seqüência de expressões: Add(Succ(Succ(Zero)),Succ(Succ(Succ(Zero)))) 2.2

que conforme a linha 9 será igual a Succ(Add(Succ(Zero),Succ(Succ(Succ(Zero))))) novamente, conforme a linha 9 será igual a Succ(Succ(Add(Zero, Succ(Succ(Succ(Zero)))))) e finalmente, conforme a linha 8 será igual a Succ(Succ(Succ(Succ(Succ(Zero))))) que corresponde ao natural 5. Obviamente que esta não é a maneira de implementar a adição e muito menos os naturais são definidos desta maneira numa linguagem de programação Na prática, representamos os naturais usando seqüências de bits que equivalem à estrutura de dados normalmente usada nos computadores (os bytes) O que deve ficar bem claro, contudo, é que a representação que escolhemos para um TAD na nossa linguagem de programação deve obedecer ao comportamento definido através da especificação algébrica 2.1. Representação de Tipos de Dados Vimos no Capítulo 1 um tipo como um conjunto de valores Esta visão é razoável para muitos propósitos, mas pode acarretar problemas quando se define um novo tipo em termos de tipos já existes Por exemplo, suponha que numa aplicação que estamos desenvolvendo precise de uma estrutura de dados com o comportamento de uma pilha. Seria interessante que a linguagem empregada suportasse um tipo predefinido chamado Pilha e que bastasse declarar uma variável deste tipo, do mesmo modo como fazemos quando declaramos um array. 2.3

Entretanto, a maioria das linguagem não oferece estas facilidades Para definir um novo tipo, em geral, usamos uma representação para seus valores, com base em valores de um tipo que já existe Muitas vezes esta representação tem propriedades não desejáveis! Exemplo: suponha que queremos definir um tipo cujos valores serão os números racionais, com operações aritméticas que são exatas. Na linguagem de programação ML, podemos escrever as seguintes declarações datatype rational = rat of (int * int); val zero = rat(0,1) and one = rat(1,1) fun op ++(rat(m 1,n 1 ): rational, rat(m 2,n 2 ): rational) = rat(m 1 *n 2 +m 2 *n 1,n 1 *n 2 ) Cada número racional é representado por um par de inteiros rotulado, onde o primeiro elemento é o numerador e o segundo o denominador 3 2 é representado por rat(3,2), mas também pode ser representado por rat(6,4), rat(9,6), rat(-3,-2), etc Os números racionais que estes pares rotulados supostamente representam são matematicamente iguais, mas os pares em si, são todos distintos Considere a seguinte comparação: if one ++ rat(1,2) = rat(6,4) then... else... mas rat(3,2) rat(6,4) Esta desigualdade é devida a representação escolhida, sendo uma propriedade (comportamento) indesejada, já que os números são matematicamente iguais!!! Outro comportamento indesejado é que não existe nada que previna um par rotulado como rat(0,0) ou rat(1,0), que não correspondem a qualquer número racional 2.4

O conjunto de valores do tipo definido anteriormente é Rational = { rat( m, n) m, n Integer} Idealmente queríamos definir o seguinte conjunto de valores { rat( m, n) m, n Integer; n>0; m e n sem fatores em comun } mas ML não tem um tipo com este conjunto de valores Deste modo, a definição dos números racionais em termos de um tipo existente é insatisfatório A seguir, mostraremos um resumo das dificuldades que podem surgir, em geral, quando nós representamos um tipo abstrato por outro tipo, o tipo concreto ou representacional: O tipo representacional pode ter valores que não correspondem a qualquer valor do tipo abstrato desejado O tipo representacional pode ter vários valores que correspondem a um mesmo valor no tipo abstrato desejado A menos que se use uma declaração de novo tipo, os valores do tipo abstrato desejado pode se confundir com valores do tipo representacional Deste modo, como implementar um TAD numa linguagem de programação, de modo que as propriedades indesejáveis do tipo representacional sejam suprimidas, com a implementação refletindo estritamente o comportamento do TAD? A chave para responder a esta pergunta será vista na seção seguinte 2.5

2.2. Independência de Representação Vimos que uma especificação abstrata (TAD) define o comportamento de um tipo de dado sem se preocupar com sua implementação Uma representação concreta (através de um tipo concreto ou representacional) nos diz como um TAD é implementado, como seus dados são colocados dentro do computador e como estes dados são manipulados por suas operações A chave para se conseguir verdadeiramente implementar tipos abstratos de dados é aplicar o conceito de Independência de Representação: Um programa deveria ser projetado de forma que a representação de um tipo de dado possa ser modificada sem que isto interfira no restante do programa A aplicação deste conceito é possível em linguagens de programação que suportem módulos Um módulo é qualquer unidade nomeada de um programa que pode ser implementada como uma entidade relativamente independente Tipicamente, um módulo é um grupo de vários componentes (tipos, variáveis, constantes, funções, procedimentos, etc) declarados com um propósito específico Dizemos que um módulo encapsula seus componentes Em geral, apenas uma pequena parte dos componentes de um módulo são visíveis externamente, são os componentes exportados pelo módulo Os demais componentes permanecem escondidos dentro do módulo, sendo usados apenas para ajudar na implementação dos componentes exportados Assim, um TAD pode ser implementado usando um módulo da seguinte maneira: 2.6

1. O nome do módulo é o nome do TAD 2. Apenas as operações da especificação abstrata são visíveis externamente ao módulo 3. A representação concreta do TAD e outros componentes auxiliares ficam ocultos dentro do módulo Uma característica importante da aplicação da independência da representação é que qualquer alteração na representação concreta, que não altere as propriedades abstratas do TAD definido, fica restrita à parte do módulo que é oculta, não afetando o resto do programa; De forma similar, uma mudança no programa, que usa as abstrações de dados, não afeta a exatidão do módulo que implementa o TAD 2.3. Exemplo de um TAD Vamos agora implementar os racionais como um TAD em ML abstype rational = rat of (int * int) with val zero = rat(0,1) and one = rat(1,1); fun op //(m: int, n: int) = if n <> 0 then rat(m, n) else (* error *) and op ++(rat(m 1,n 1 ): rational, rat(m 2,n 2 ): rational) = rat(m 1 *n 2 +m 2 *n 1,n 1 *n 2 ) end and op ==(rat(m 1,n 1 ): rational, rat(m 2,n 2 ): rational) = (m 1 *n 2 = m 2 *n 1 ) Esta declaração abstype implementa um TAD chamado rational através de um módulo que define os seguintes componentes: as constantes zero e one; as operações //, ++ e ==, que são os únicos componentes visíveis do módulo. 2.7

A representação concreta (pares de inteiros) escolhida para valores do novo tipo é oculta do usuário do tipo, bem como a implementação das funções O único meio para o usuário gerar valores do tipo rational é pela avaliação de expressões envolvendo as constantes zero e one e as funções //, ++. Estes valores só podem ser comparados chamando a função == Logo, o seguinte código trabalhará como deve: val h = 1//2;... if (one ++ h) == 6//4 then... else... Agora, não importa que um dado valor tenha várias representações possíveis, porque estas representações são ocultadas do usuário O que é importante é que apenas propriedades desejáveis dos valores são observáveis usando as operações associadas com o tipo abstrato Ex.: no exemplo anterior, a diferença entre as representações rat(3,2) e rat(6,4) não são observáveis, porque a função == as trata como iguais Em geral, uma implementação de um TAD deve prover operações de construção para compor (criar) valores do tipo abstrato e operações de destruição, para decompor estes valores No exemplo anterior, a função // é necessária para permitir que valores racionais sejam compostos. zero e one são também exemplos de operações de construção. Um possível destrutor seria fun float(rat(m, n): rational) = m/n; Implementações de TADs são similares aos tipos predefinidos, como os inteiros e booleanos. Por que? 2.8