Carregar apresentação
A apresentação está carregando. Por favor, espere
PublicouBenedito Leal Frade Alterado mais de 8 anos atrás
1
Estrutura de Dados Prof. André Cypriano M. Costa amonteiro@catolica-es.edu.br acostaprofessor@gmail.com
2
Muitos dos programas que desenvolvemos possuem tipos de dados que são característicos de cada programa. E para que possamos fazer uma programação segura, precisamos definir claramente esse tipo de dados e como fazer para acessar as informações que ele armazena. Desta forma precisamos definir um Tipo Abstrato de Dados. 2
3
Um Tipo de Dados é um conjunto de valores munido de um conjunto de operações. Um exemplo de tipo de dados são: int, float, char Já um Tipo Abstrato de Dados (TAD) especifica uma classe de dados definida pelo usuário em termos de suas propriedades abstratas: Descreve o comportamento de um objeto que independe da sua implementação, unicamente através dessas propriedades (funções ou métodos) abstratas Não há preocupação de como essas propriedades seriam implementadas numa linguagem de programação 3
4
A especificação de um TAD é composto de três partes: 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 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 Especificação das Restrições: estabelece as condições que devem ser satisfeitas antes e depois da aplicação das operações Exemplos de TADs: Listas, pilhas, filas, árvores, etc. 4
5
Um TAD define o comportamento de um tipo de dado sem se preocupar com sua implementação. Entretanto, esta especificação não é reconhecida pelo computador. É preciso criar uma representação concreta (através de um tipo concreto ou representacional) que 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 (funções). 5
6
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 é melhor realizada através da modularização do programa. 6
7
Vamos agora mostrar a especificação dos números naturais como um TAD. Definiremos os naturais Nat = {0, 1, 2, 3,...} com as seguintes operações: Teste de zero Soma e Igualdade através da seguinte especificação 7
8
ABSTRACT Nat sintaxe 1Zero() → Nat 2ehZero(Nat) → Boolean 3Suc(Nat) → Nat 4Add(Nat, Nat) → Nat 5Eq(Nat, Nat) → Boolean 8
9
ABSTRACT Nat semantica ∀ x, y ∈ Nat 6ehZero(Zero()) = true 7ehZero(Suc(x)) = false 8Add(Zero(), y) = y 9Add(Suc(x),y) = Suc(Add(x, y)) 10Eq(x, Zero()) = if IsZero(x) then true else false 11Eq(Zero(), Suc(y)) = false 12Eq(Suc(x),Suc(y)) = Eq(x, y) restrictions end 9
10
Zero() é a função constante que significa não precisar de argumento de entrada e o seu resultado é o número natural 0 (zero). ehZero() é 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. Suc() significa o sucessor do número passado como parâmetro. 10
11
Usando Zero e Suc podemos definir todos os números naturais como: 0 = Zero() 1 = Suc(Zero()) 2 = Suc(Suc(Zero())) 3 = Suc(Suc(Suc(Zero())))... 11
12
As regras das linhas 8 (Add(Zero(), y) = y) e 9 (Add(Suc(x),y) = Suc(Add(x, y))) 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(Suc(Suc(Zero())), Suc(Suc(Suc(Zero())))) = Suc(Add(Suc(Zero()), Suc(Suc(Suc(Zero()))))) = Suc(Suc(Add(Zero(), Suc(Suc(Suc(Zero())))))) = Suc(Suc(Suc(Suc(Suc(Zero()))))) que corresponde ao natural 5. 12
13
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. 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. 13
14
Vamos considerar a criação de um TAD para representar um ponto no espaçp R 2. Para isso, devemos definir um tipo abstrato, que denominaremos de Ponto, e o conjunto de funções que operam sobre esse tipo. Neste exemplo, vamos considerar as seguintes operações: cria: operação que cria um ponto com coordenadas x e y; libera: operação que libera a memória alocada por um ponto; acessa: operação que devolve as coordenadas de um ponto; atribui: operação que atribui novos valores às coordenadas de um ponto; distancia: operação que calcula a distância entre dois pontos. 14
15
A interface desse módulo pode ser dada pelo código a seguir: Arquivo.h // TAD: Ponto (x,y) typedef struct ponto Ponto; // Função cria: Aloca e retorna um ponto com coordenadas (x,y) Ponto* cria (float x, float y); 15
16
// Função libera: Libera a memória de um ponto previamente // criado. void libera (Ponto *p); / Função atribui: Atribui novos valores às coordenadas de um // ponto void atribui (Ponto *p, float x, float y); // Função distancia: Retorna a distância entre dois pontos float distancia (Ponto *p1, Ponto *p2); 16
17
Os programas que quiserem utilizar esse TAD só terão acesso às informações que possam ser obtidas através das funções exportadas pelo arquivo ponto.h. Agora, mostraremos uma implementação para esse tipo abstrato de dados. O arquivo de implementação do módulo (arquivo ponto.c) deve sempre incluir o arquivo de interface do módulo. 17
18
Isto é necessário por duas razões: Podem existir definições na interface que são necessárias na implementação. No nosso caso, por exemplo, precisamos da definição do tipo Ponto. É garantirmos que as funções implementadas correspondem às funções da interface. Como o protótipo das funções exportadas é incluído, o compilador verifica, por exemplo, se os parâmetros das funções implementadas equivalem aos parâmetros dos protótipos. 18
19
Ponto.c #include #include "ponto.h” Essas são as bibliotecas necessárias para o programa. 19
20
Como só precisamos guardar as coordenadas de um ponto, podemos definir a estrutura ponto da seguinte forma: struct ponto { float x; float y; }; 20
21
A função que cria um ponto dinamicamente deve alocar a estrutura que representa o ponto e inicializar os seus campos: Ponto* cria (float x, float y) { Ponto* p = (Ponto*) malloc(sizeof(Ponto)); if (p == NULL) { printf("Memória insuficiente!\n"); exit(1); } p->x = x; p->y = y; return p; } 21
22
Para esse TAD, a função que libera um ponto deve apenas liberar a estrutura que foi criada dinamicamente através da função cria: void libera (Ponto* p) { free(p); } 22
23
A função para atribuir valores às coordenadas de um ponto é de fácil implementação, como pode ser visto a seguir. void atribui (Ponto* p, float x, float y) { p->x = x; p->y = y; } 23
24
Já a operação para calcular a distância entre dois pontos pode ser implementada da seguinte forma: float distancia (Ponto *p1, Ponto *p2) { float dx = p2->x – p1->x; float dy = p2->y – p1->y; return sqrt(dx*dx + dy*dy); } 24
Apresentações semelhantes
© 2024 SlidePlayer.com.br Inc.
All rights reserved.