23
AED (IST/DEEC) 60 Tipos abstractos [1] Balanço dos tipos de dados no C (básicos, estruturados, dinâmicos e composições) Vantagens: muito próximos dos tipos das linguagem máquina (Bit,Word) manipulação eficiente Inconvenientes: Porque os algoritmos são expressos por instruções simples (=, if, do,...) resultam muitas vezes em falhas de implementação tipo de linguagem muito afastada do raciocínio dos analistas Mesmo que o algoritmo seja igual, a alteração do tipo de dados obriga a modificar o código (exemplo: se nas listas da aula anterior for alterado o tipo do campo item, de int para char, a função newElement temde ser modificada) Solução: usar abstracções que permitem descrever o problema, deixando os detalhes de implementação para depois! AED (IST/DEEC) 61 Tipos abstractos [2] Um tipo abstracto é um tipo genérico de dados, dos quais não se conhece os valores uma interface que define os acessos e as operações sobre os dados O conjunto das propriedades algébricas da interface, que delimitam as possíveis implementações. A implementação transcreve o tipo abstracto, codificando os programas que efectuam as operações definidas na interface (satisfazendo as propriedades). O uso permite compilar a implementação, instanciando o tipo genérico para um dos tipos de C Um programa que usa um tipo abstracto é um cliente . O cliente não tem acesso à implementação.

Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

  • Upload
    buimien

  • View
    215

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 60

Tipos abstractos [1]• Balanço dos tipos de dados no C (básicos, estruturados, dinâmicos e

composições)– Vantagens:

• muito próximos dos tipos das linguagem máquina (Bit,Word)• manipulação eficiente

– Inconvenientes:• Porque os algoritmos são expressos por instruções simples (=, if, do,...)

– resultam muitas vezes em falhas de implementação– tipo de linguagem muito afastada do raciocínio dos analistas

• Mesmo que o algoritmo seja igual, a alteração do tipo de dados obriga a modificar o código (exemplo: se nas listas da aula anterior for alterado o tipo do campo item, de int para char, a função newElement temde ser modificada)

• Solução: usar abstracções que permitem descrever o problema, deixando os detalhes de implementação para depois!

AED (IST/DEEC) 61

Tipos abstractos [2]

• Um tipo abstracto é• um tipo genérico de dados, dos quais não se conhece os valores• uma interface que define os acessos e as operações sobre os dados• O conjunto das propriedades algébricas da interface, que delimitam as

possíveis implementações.

• A implementação transcreve o tipo abstracto, codificando os programas que efectuam as operações definidas na interface (satisfazendo as propriedades).

• O uso permite compilar a implementação, instanciando o tipo genérico para um dos tipos de C

Um programa que usa um tipo abstracto é um cliente. O cliente não tem acesso à implementação.

Page 2: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 62

Tipos abstractos [3]Exemplo dos passos no desenvolvimento de um programa1. Análise:

1. [Especificação] entram números codificados, sendo depois devolvidos o valor decifrados.

2. [Tipo abstracto de dados] operações: entrada e remoção de elementos de uma lista genérica, cifra e descodificação.

2. Implementação:– Opção A: Tipo de dados por tabela, com índice para o primeiro índice livre– Opção B: Tipo de dados por lista simplesmente ligada– Cifra/descodificação por chave pública

3. Uso– (Opção B) O tipo de dados é uma lista simplesmente ligada de inteiros.

4. Compilação– 0’s e 1’s, do processador

AED (IST/DEEC) 63

ContentoresMuitos tipos abstractos representam contentores. Os contentores

servem para armazenar um conjunto de items: listas, pilhas, anéis, tabelas de dispersão (‘‘hash-tables’’), ...

Para definir um tipo abstracto para um contentor deve-se:1. Definir a interface do tipo abstracto em função do tipo Item.

A interface inclui o ficheiro “Item.h” (que contém a definição do tipo),

2. Definir a implementação,3. Cada cliente cria um ficheiro “Item.h”, consoante as suas

necessidades.4. Compilar

Page 3: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 64

Exemplo: Pilha [1]Operações abstractas

- inicialização.

- limpeza da pilha.

- colocação de um elemento na pilha.

- remoção de um elemento (o último colocado).

- indica se pilha está vazia.

Usando a mesma interface, podem ser definidas várias implementações ...

Pilha.htypedef enum {FALSE,TRUE} BOOL;void Init(unsigned pNumb);/*parâmetro é comprimento máximo*/int Empty();void Push(Item pI);Item Pop();BOOL IsEmpty();

AED (IST/DEEC) 65

Exemplo: Pilha [2]Algumas propriedades algébricas da pilha

TODO n: IsEmpty(Init(n))=TRUE ; pilha é sempre inicializada vazia

TODO i: IsEmpty(Push(i))=FALSE ; depois de inserido um elemento,

; nunca a pilha fica vazia*/

TODO i: Pop(Push(i))=i ; elemento removido da pilha é sempre o último

; a ser inserido

Para os mais curiosos, apenas! Na definição algébrica da pilha, ela própria é um tipo genérico Stack. A interface e as propriedades são um pouco diferentes.

A implementação é um pouco mais complexa, pelo que não é considerada aqui.

• Stack Init(int pNumb)• Stack Push(Stack pStk, int pNumb)• Stack Pop(Stack pStk)• int Top(Stack)

•TODO i,p: Top(Push(p,i))=i•TODO i,p: Pop(Push(p,i))=p ; push seguido de

; pop mantém pilha

Page 4: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 66

Exemplo: Pilha [3]

Pilha.c#include “Item.h” /* aqui o cliente define

os dados */#include “Pilha.h”static Item *gP;static int gN; /*primeiro índice livre*/

void Init(unsigned pSize) {gP = (Item *)malloc(pSize*sizeof(Item));gN = 0; }

void Push(Item pI) {gP[gN++] = pI; }

BOOL IsEmpty() {return gN==0? TRUE : FALSE; }

...

Implementação do tipo pilha usando uma tabela

Vantagens:

• Simplicidade.

Desvantagens:

• Tamanho máximo limitado à partida.

i1i2

gN=2

Push(i3)

i1

i3i2

gN=3

AED (IST/DEEC) 67

Exemplo: Pilha [4]

Pilha.c#include “Item.h”#include “Pilha.h”typedef struct pilha {Item item;struct pilha *next;

} pilha;static pilha *gP;

void Init(unsigned pNumb) {gP = NULL; }

void Push(Item pI) {pilha *Top = (pilha *)malloc(sizeof(pilha));Top->item = pI; Top->next = gP;gP = Top;}

BOOL IsEmpty() {return gP==NULL? TRUE : FALSE; } ...

Implementação do tipo pilha usando uma listaVantagens:

• Cresce à medida que novos elementos são postos na pilha.• Decresce quando se removem elementos.

Desvantagens:

• Ocupa mais memória (para os apontadores).• Mais lento (gestão da memória).

Push(i3)

i2 i1

i2 i1i3

gP

gP

Page 5: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 68

Exemplo: Pilha [5]Utilização do tipo abstracto pilha por clientes

Vários clientes podem dar definições diferentes para o tipo Item de modo a usar, por exemplo:

• Uma pilha de alunos

Item.htypedef struct {

unsigned numero;enum {LEEC,LEIC,LERCI} curso;char *nome;

} Item;

• Uma pilha de inteiros

Item.htypedef int Item;

AED (IST/DEEC) 69

Exemplo: Pilha [6]Intstack.c (cliente 1):#include “Item.h”#include “Pilha.h”main() {

Item Val=100;Init(19);Push(Val); }

Alunos.c (cliente 2):#include “Item.h”#include “Pilha.h”Item InicializarAluno(char *pName,int pNumb){

...}main(){

Item Aluno;init(0);Aluno=InicializarAluno(“José”,44562);Push(Aluno);}

Atenção! O ficheiro “Item.h” é incluído antes do ficheiro “Pilha.h” de modo a definir o tipo Item referido neste ficheiro.

Page 6: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 70

Exemplo: Pilha [7]• Comparando os dois clientes, as diferenças resumem-se a:

• Ficheiro de definições Item.h• Programa principal

Os tipos de dados abstractos permitem reutilizar funções (a nível de programas fonte).

Atenção: não é o mesmo que a reutilização de bibliotecas (‘‘library’’) objecto, nestas os tipos de dados não podem ser definidos pelos clientes.

AED (IST/DEEC) 71

Exemplo: Pilha [8]Exemplo de aplicação do tipo abstracto de pilha: pretende-se validar expressões

aritméticas em notação pós-fixada (considerados apenas operadores soma e multiplicação).

Explicação: Os operadores aritméticos binários, são colocados segundo a notação:– In-fixada: entre os operandos (usada pelos humanos, mas obriga a definir prioridades-

multiplicação maior que soma, e usar parêntesis para tornear as prioridades.Ex: 2 + 3 *4 [resultado 14], (2 +3)*4 [resultado 20]

– Pós-fixada: depois dos operandos (usada pelos computadores, cálculo efectuado logo que se encontra o operador o que evita definição de prioridades e parêntesis)

Ex: 2 3 4 * + [resultado 14], 2 3 + 4 * [resultado 20]Método de cálculo de 2 3 4 * +(a) inserir 2 na pilha(b) inserir 3 na pilha(c) inserir 4 na pilha(d) detectada a multiplicação, retirar os dois operandos da pilha «4»,«3» e inserir o resultado «12»(e) detectada a soma, retirar os dois operandos da pilha «2»,«12» e inserir o resultado «14»(f) Só há um operando na pilha: a expressão 2 3 4 * + é válida!

Page 7: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 72

Exemplo: Pilha [9]#include <stdio.h>#include <string.h>#include “Item.h” /* O cliente usa pilha de inteiros */ #include “Pilha.h”

main(int pArgc, char **pArgv) {int Idx, Res, Dim = pArgc-1;

Init(Dim);for (Idx = 1; Idx <= Dim; Idx ++) {

if (!strcmp(pArgv[Idx],”+”)) Push(Pop() + Pop());else if (!strcmp(pArgv[Idx],”*”)) Push(Pop() * Pop());else Push(atoi(pArgv[Idx]));

}Res = Pop();if (IsEmpty()) printf(“Valido com resultado=%d\n”, Res);else printf(“Expressao invalida!\n”); }

AED (IST/DEEC) 73

Implementações

• O cliente não depende da implementação.• O cliente não tem de saber como a pilha foi implementada.• Escolha-se a implementação na altura da edição de ligações

(‘‘link’’) do programa.• A escolha deve ser feita em função da aplicação. • Em muitos casos as diferenças estão na gestão da memória:

– Uma gestão mais rígida (baseada em tabelas) tem o defeito que é preciso conhecer o tamanho máximo à partida. O espaço ocupado em memória corresponde sempre ao tamanho máximo.

– Uma gestão mais flexível (baseada em listas, por exemplo) tem o defeito de ser menos eficiente (tempo de computação) mas permite o tratamento de problemas maiores devido a uma gestão mais apertada da memória.

Page 8: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 74

• Tipos abstractos

• Contentores

• Pilhas– Implementação em tabela

– Implementação em lista

• Critérios para escolha da implementação

Síntese da Aula 4 de Tipologia e Operações

AED (IST/DEEC) 75

Tipos de 1ª classe

Os tipos abstractos que já vimos têm um defeito:• Só pode existir uma única instância do tipo por programa.

(definida como variável estática na parte da implementação)

O ideal seria poder usar os tipos abstractos da uma maneirasemelhante aos tipos básicos (int, float, char etc..). Def: Um tipo de 1ª classe é um tipo para o qual pode haver muitas

instâncias que podem ser atribuídas a variáveis do programa. Os tipos de 1ª classe podem ser usados nas declarações como os tipos básicos.

Page 9: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 76

Exemplo: tipo complexo [1]

O tipo de 1ª classe complexo é definido pela interface:

Complex.h:

typedef struct{float Re; float Im;} Complex;

Complex ComplexInit(float pRe, float pIm);float Re(Complex pC);float Im(Complex pC);Complex mult(Complex pC1, Complex pC2);

O ficheiro Complex.c contém a implementação...

AED (IST/DEEC) 77

Exemplo: tipo complexo [2]#include “Complex.h”Complex ComplexInit(float pRe, float pIm) {

Complex Res;Res.Re = pRe; Res.Im = pIm; return Res;}

float Re (Complex pC) { return pC.Re; }float Im (Complex pC) { return pC.Im; }

Complex mult(Complex pC1, Complex pC2) {return ComplexInit(Re(pC1)* Re(pC2)– Im(pC1)* Im(pC2),

Re(pC1)* Im(pC2)+ Im(pC1)* Re(pC2));}

Page 10: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 78

Exemplo: tipo complexo [3]O programa cliente calcula as raízes complexas da equação zN = 1. As raízes são dadas pela fórmula : cos(2πk/N) + i sin(2πk/N).#include <math.h>#include “Complex.h”main (int pArgc, char **pArgv) {

int Idx1, Idx2, pN = atoi(pArgv[1]);Complex t, x;printf(“raízes para N=%d\n”, pN);for (Idx1=0; Idx1 < pN; Idx1++) {

float r = 2.0 * M_PI * Idx1 / pN;t = ComplexInit(cos(r), sin(r));printf(“Z%d: %6.3f %6.3f\t“, Idx1, Re(t), Im(t));for (x=t, Idx2=0; Idx2 < pN-1; Idx2++) x = mult(t,x);printf(“Z%d^%d = %6.3f %6.3f\n”, Idx1, pN, Re(x),Im(x));}

}

Compilação requer biblioteca de funções matemáticas: usargcc –o roots roots.c Complex.c -lm

AED (IST/DEEC) 79

Exemplo: tipo complexo [4]

Neste exemplo, podemos observar que:• O tipo Complex é usado como se fosse um tipo predefinido,• Certas linguagens de programação (por exemplo o Java)

permitem a definição de operadores (+,-,*,/, etc...) para tipos novos. (No Java podíamos ter definido um novo * em vez de mult).

• Apesar de o cliente ser independente da implementação, tem acesso à forma como foi implementado o tipo (a definição do tipo está visível na interface)

→ perigo potencial ...

Page 11: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 80

Exemplo: tipo complexo [5]

Se o cliente tiver acesso à definição do tipo:• Tem a possibilidade de aceder directamente aos campos da

estrutura:– Pode usar t.Re em vez de Re(t).

• Os programas clientes tornam-se dependentes da implementação.– se a implementação for alterada (usando, por exemplo a notação polar ou

angular para os complexos), é necessário alterar todos os ficheiros clientes.

A solução consiste em esconder a definição do tipo.

AED (IST/DEEC) 81

Complexos, 2ª versão [1]

• A interface passa a ser:

typedef struct complex *Complex;

Complex ComplexInit(float pRe, float pIm);float Re(Complex pC);float Im(Complex pC);Complex mult(Complex pC1, Complex pC2);

A diferença reside na definição do tipo Complex como apontador para uma estrutura. A estrutura não está definida neste ficheiro.

Page 12: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 82

Complexos, 2ª versão [2]

A implementação é alterada:• A estrutura complex é definida:

struct complex { float Re; float Im; };• A memória deve ser alocada na função init:

Complex ComplexInit (float pRe, float pIm) {Complex Res =(Complex)malloc(sizeof(struct complex));Res->Re = pRe; Res->Im = pIm; return Res;

}• O tipo Complex é um apontador portanto os acessos aos campos é

feito com -> em vez do ponto.

AED (IST/DEEC) 83

Complexos, 2ª versão [3]

• O cliente não precisa de ser alterado.Resumindo:• O tipo é escondido usando um apontador (Complexo é um

ponteiro)• O tipo é definido na implementação.

Não era possível implementar esta solução sem recorrer a um apontador. O apontador permite criar um tipo sem especificar os pormenores. O compilador pode compilar um programa (interface + cliente) porque o tipo Complexo tem um tamanho definido : 32bits.

Page 13: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 84

Exemplo: Filas [1]Def: Na fila, ou FIFO-First In/First Out, o primeiro elemento a sair é o primeiro elemento entrado. Em relação às pilhas, as alterações relevantes são:

• A inserção de um elemento é feita no fim da lista.

• Passa a haver dois ponteiros, um para o início da lista (para retirar elementos) outro para o fim da lista (para inserir elementos).

Fila.h:

typedef struct fila *F;void FilaDump(F); F FilaInit(int);int FilaEmpty(F);void FilaPut(F, Item);Item FilaGet(F);

AED (IST/DEEC) 85

Exemplo: Filas [2]Implementação Fila.c (usando uma lista):#include <stdlib.h>#include <stdio.h>#include “Item.h”#include “Fila.h”

Item.h define o tipo de dado contido na fila. A fila é implementada usando uma lista:

typedef struct _element { Item item; struct _element * next;

} element;

A estrutura fila usada na interface é definida:struct fila { element * primeiro; element * ultimo; };

Page 14: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 86

Exemplo: Filas [3]

A função new serve para alocar e inicializar um novo elemento na lista:

element *FilaNew(Item vItem, element *pNext) {element *x = (element *) malloc(sizeof (element));x->item = vItem; x->next = pNext; return x;

}

Função de inicialização de uma fila. Dado que está implementada com uma lista, não estamos limitados no número de elementos.

F FilaInit(int maxN) {F pFila = (F) malloc(sizeof(struct fila));pFila->primeiro = NULL; return pFila;

}

AED (IST/DEEC) 87

Exemplo: Filas (4)Função que coloca um item na fila:void FilaPut(F pFila, Item vI) {

if (pFila->primeiro == NULL) { /* a fila está vazia */pFila->ultimo = FilaNew(vI, pFila->primeiro);pFila->primeiro = pFila->ultimo; return; }

/* o item é colocado no fim da lista */pFila->ultimo->next = FilaNew(vI, NULL);pFila->ultimo = pFila->ultimo->next;}

Fila após inicialização

0primeiro ultimo

Fila com 1 elemento

primeiro ultimo0

item

next

Fila com 2 elementos

primeiro ultimo0

Page 15: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 88

Exemplo: Filas [5]

A função get remove o primeiro elemento da fila:

Item FilaGet(F pFila) {Item item = pFila->primeiro->item;element *elem = pFila->primeiro->next;free(pFila->primeiro); pFila->primeiro = elem;return item;

} A medida que os elementos são removidos da lista, a memória é

libertada.

AED (IST/DEEC) 89

• Tipos abstractos de 1ª classe

• Exemplo para Complexos

• Exemplo para Filas

Síntese da Aula 5 de Tipologia e Operações

Page 16: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 90

Contentores

• O exemplo do tipo fila demonstra a possibilidade de criar tipos de 1ª classe para novos contentores.

• Os contentores criados até agora dependem de um tipo Itemque representa o tipo de dados que se quer armazenar no contentor

• Um defeito desta abordagem é que num programa o tipo Itemsó pode ser definido uma única vez.

• Em consequência não podemos ter no mesmo programa, uma fila de inteiros e uma fila de elementos de tipo «aluno».

AED (IST/DEEC) 91

Items

• A solução consiste, como no caso dos tipos de 1ª classe, em usar um ponteiro de modo a não especificar o tipo dos items.

• O tipo Item é definido por:typedef void * Item;O tipo void * corresponde a um apontador para um objecto cujo tipo é

desconhecido.

• Vamos agora, criar filas de vários tipos.

Page 17: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 92

Filas de complexos

Para criar filas de complexos, o cliente pode usar o tipo Complexjá definido:

F pFilaC = FilaInit(10); /* declaração da fila *//* declaração de um complexo: */Complex z = ComplexInit(1,1); Para colocar o complexo na fila:FilaPut(pFilaC, (Item) z);A variável z é um apontador, o cast permite evitar obter warnings do

compilador. Para remover um elemento da fila:z = (Complex) FilaGet(pFilaC);Portanto, é preciso: • converter os Item para Complex quando ler da fila • converter os Complex para Item quando escrever para a fila

AED (IST/DEEC) 93

Filas de matrizes [1]Para definir filas de matrizes, temos de definir primeiro um tipo

abstracto Matrix:Interface: Matrix.htypedef struct _matrix * Matrix;Matrix MatrixNew(int, int);Matrix MatrixMult(Matrix, Matrix);float MatrixElement(Matrix,int,int);etc...Implementation: Matrix.ctypedef struct _matrix {

float ** valores;int cols; int rows;

} matrix;

Page 18: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 94

Filas de matrizes [2]Matrix NewMatrix(int pRows, int pCols) {

int Idx;Matrix Mat = (Matrix) malloc(sizeof(matrix));Mat->valores = (float **) malloc(pRows * sizeof (float *));for (Idx =0; Idx < pRows; Idx++)Mat->valores[Idx] = (float *) malloc(pCols * sizeof(float));

Mat->rows=pRows; Mat->cols=pCols; return Mat;}

Matrix MatrixMult(Matrix pA, Matrix pB) {Matrix Res = NewMatrix(Rows(pA), Cols(pB));int IdxI,IdxJ,IdxK;...return Res;

}

AED (IST/DEEC) 95

Filas de matrizes [3]float MatrixElement(Matrix pA, int pI, int pJ) {

return pA->valores[pI][pJ];}Uma vez o tipo Matrix definido, o cliente pode criar uma fila de matrizes:F pFilaM = FilaInit(10);Matrix m = NewMatrix(10,10);Colocar m na fila:FilaPut(pFilaM,(Item) m);Para remover uma matriz da fila:Matrix a = (Matrix) FilaGet(pFilaM);• As filas de matrizes e as filas de complexos podem coexistir no mesmo

programa. • O Item aponta para um complexo ou para uma matriz.

Page 19: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 96

Listas duplamente ligadas [1]As filas duplamente ligadas são usadas quando é preciso percorrer a lista do

início até ao fim e do fim até ao início.A interface dlist.h:

typedef struct dlist * Dl;Dl NewDList();Dl AddAtEnd(Item, Dl);Dl AddAtHead(Item, Dl);Dl Concat(Dl,Dl);Item First(Dl);Item Last(Dl);Item Next(Dl);Item Previous(Dl);Item Nth(Dl, int n);Item Find(Item, Dl, int test(Item,Item));void Apply( void f(Item), Dl);

AED (IST/DEEC) 97

A lista vazia é representada por um ponteiro nulo:Dl NewDlist() {

return (Dl) NULL; }

Implementação: dlist.c.Definição do tipo dlist:

typedef struct _dlist { Item item; struct _dlist * next; struct _dlist * previous;

} dlist;

A inserção de um item no início da lista éfeito pela função seguinte:

Dl AddAtHead(Item item, Dl list) {

Dl n = malloc(sizeof(dlist)); n->previous = NULL;n->item = item;if (list != NULL) {

n->next = list; list->previous = n;

}return n;

}

Listas duplamente ligadas [2]

Page 20: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 98

Listas duplamente ligadas [3]A função AddAtEnd acrescenta um elemento ao fim da lista:Dl last(Dl l) {

Dl ultimo = l;while (ultimo->next != NULL)

ultimo = ultimo->next;return ultimo;

}Dl AddAtEnd(Item i, Dl list) {

Dl ultimo = last(list);ultimo->next = malloc(sizeof(dlist));ultimo->next->item = i;ultimo->next->previous = ultimo;ultimo->next->next = NULL;return list;

}

AED (IST/DEEC) 99

Listas duplamente ligadas [4]Para concatenar duas listas:Dl Concat(Dl l1,Dl l2) {

Dl l3 = last(l1);l3->next = l2; l2->previous = l3;return l1;

}Vários acessores:Item First(Dl l) { return l->item; }Item Last(Dl l) { return last(l)->item; }Item Next(Dl l) { return l->next->item; } Item Previous(Dl l) { return l->previous->item; }Nth devolve o nésimo item da lista:Item Nth(Dl l, int n) {

int i;for (i=0; i<n; i++) l = l-> next; return l->item;

}

Page 21: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 100

Listas duplamente ligadas [5]

A função Find ilustra a utilidade de passar funções em argumento:Item Find(Item i, Dl l, int test(Item,Item)) {

while (!(test(i,l->item)) &&l->next != NULL) l = l->next;

if (l->next == NULL)if (test(i,l->item))

return l->item;else return (Item)NULL;

return l->item;}O terceiro argumento da função é uma função de comparação entre

2 items. O utilizador escreve a função de teste em conformidade com o objectivo da procura.

AED (IST/DEEC) 101

Listas duplamente ligadas [6]

• A função Apply recebe em argumento uma função que admite como argumento um item.

• Aplica a função f a todos os elementos da lista.• A vantagem para o cliente é que não tem de escrever muitos dos

ciclos que iteram sobre a lista.

void Apply( void f(Item), Dl l) {while (l != NULL) {

(f)(l->item);l = l-> next;

}}

Page 22: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 102

Listas duplamente ligadas [7]O cliente pode usar, por exemplo listas de alunos.Primeiro deve-se definir um tipo abstracto para o aluno:typedef struct _aluno *Aluno; /* na interface */Implementado por:typedef struct _aluno { char *nome; int num; } aluno;

O tipo abstracto aluno define a função de igualdade:int AlunoIgual(Item i1, Item i2) {

return (Num((Aluno) i1) == Num((Aluno) i2));}Onde Num é definido por:int Num (Aluno a) { return a->num; };

AED (IST/DEEC) 103

Listas duplamente ligadas [8]

A procura na lista de alunos pode ser feita assim:Aluno Procura(int num, Dl l_alunos) {

Aluno a = NovoAluno(“”,num);return Find(a, l_alunos, AlunoIgual);

}

Onde NovoAluno é um construtor:Aluno NovoAluno(char * nome, int num) {

Aluno a = malloc(sizeof(aluno));a->nome = nome; a->num = num;return a;

}

Page 23: Tipos abstractos [1] - algos.inesc-id.ptalgos.inesc-id.pt/aed06/downloads/Slides/4-EstDadosB.pdf · AED (IST/DEEC) 64 Exemplo: Pilha [1] Operações abstractas-inicialização.-limpeza

AED (IST/DEEC) 104

Listas duplamente ligadas [9]

Para imprimir no écran todos os alunos contidos na lista:void PrintAlunos(Dl l_alunos) {

Apply(PrintAluno, l_alunos);}

Onde a função PrintAluno é definida por:void PrintAluno(Item a) {

printf(“Aluno nº %d, %s\n”, Num((Aluno) a), Nome((Aluno) a));

}Não é preciso escrever ciclos !

AED (IST/DEEC) 105

• Tipos abstractos de 1ª Classe

• Filas de Complexos

• Filas de matrizes

• Listas Duplamente Ligadas

Síntese da Aula 6 de Tipologia e Operações