AED (IST/DEEC) 2
Tipologia de dados [1]
• Simples
– Inteiros (int Index);
– Reais (float Stock, double Income);
– Caracteres (char Answer)
• Estruturados
– Tabelas (‘‘array’’) - estáticas ou dinâmicas: vários elementos do mesmo
tipo
• Unidimensionais (Array1[N])
• Multidimensionais (Array2[N1]...[Nk] ou Array2[N1,...,Nk])
• Acervos (Heap[N])
– Estruturas (‘‘struct’’): elementos de tipos possivelmente distintos
AED (IST/DEEC) 3
• Composições
– listas de listas, listas de estruturas, lista de tabelas, tabelas de listas, ...
AED (IST/DEEC) 4
Que estrutura de dados escolher?
• A escolha da forma como se armazenam os dados depende de
– Operações que sejam mais frequentes no algoritmo a implementar:
• Quando o acesso e modificação são a base do algoritmo, as tabelas deverão
ser escolhidas
• Quando a inserção e remoção são mais frequentes
– Usar listas simples, se estas operações ocorrem sempre no início (“STACK”)
– Usar listas simples com ponteiro adicional para o fim da lista, se a inserção se
fizer no fim e a remoção no início (“QUEUE”)
– Previsibilidade sobre a memória necessária:
• O uso de tabelas pressupõe que se saiba que memória é suficiente, ou que se
defina um valor suficientemente alto que comporte todas as instâncias de
interesse.
• Quando tal valor é incomportável, o único recurso razoável consiste em gerir
a memória dinamicamente.
AED (IST/DEEC) 5
Os literais podem ter base decimal (ex: 27, -15), octal (iniciados por 0, ex:
031) ou hexadecimal (iniciados por 0x ou 0X, ex: 0x1f5, 0XFF).
AED (IST/DEEC) 6
Tipos básicos [2]
– Reais
• double (precisão dupla) : o mais usado
• float (precisão simples)
AED (IST/DEEC) 7
AED (IST/DEEC) 8
Conversão de tipos
• Conversão implícita:
int Numb;
float Inflation;
Inflation = Numb / 3.5;
O operador / converte Numb para real antes de efectuar a divisão.
• Conversão explícita (‘‘casting’’):
int Numb1, Numb2;
float Price;
Price = ((float) Numb1) / Numb2;
AED (IST/DEEC) 9
Cada utilização do tipo é feita num ficheiro «cliente» onde o header é incluído:
#include <stdio.h> /*biblioteca*/
#include “ficheiro.h” /*declarações de projecto, no próprio directório*/
AED (IST/DEEC) 10
Definição de tipo: exemplo [1]
Ficheiro Num.h : Ficheiro Point.c:
typedef float Number; #include <math.h>
#include “Point.h”
Number distance(Point pA, Point pB)
Ficheiro Point.h : {
#include “Num.h” Number dx = pA.x – pB.x;
typedef struct { Number dy = pA.y – pB.y;
Number x; return(sqrt(dx*dx + dy*dy));
Number y; }
} Point;
Point create_point(Number x, Number y)
Number distance(Point pA, {
Point pB); Point pt;
Point create_point(Number x, pt.x = x; pt.y = y;
Number y); return pt;
}
AED (IST/DEEC) 11
#include “Point.h”
main () {
Point Pt1, Pt2;
Number Numb;
Pt1 = create_point(1.0, 2.0);
Pt2 = create_point(3.7, 4.5);
Numb = distance(Pt1, Pt2);
...
}
AED (IST/DEEC) 12
Ponteiros [1]
• A linguagem C permite aceder a posições de memória
específicas por meio de ponteiros;
• Para cada um dos tipos básicos é possível criar ponteiros;
• Exemplo:
int N1;
• Reserva uma posição de memória onde a variável “N1” irá morar;
• &N1 é o endereço de memória onde o valor de “N1” é armazenado;
int *N2;
• Reserva uma posição de memória, de nome “N2”, onde se poderá
colocar o endereço de um inteiro, ou do primeiro inteiro de uma
tabela de inteiros;
AED (IST/DEEC) 13
Ponteiros [2]
• Exemplo (continuação):
int N1; N1
??
N1 = 3; N1
3
&N1
N1
3
&N1
AED (IST/DEEC) 14
Ponteiros [3]
• Exemplo (continuação):
int *N2; N2
??
N2=&N1;
N2 N1
&N1 3 A alocação de
memória ocor-
&N1 re em qualquer
sítio, podendo
ser acima ou a-
N2 = (int *) malloc(3*sizeof(int)); baixo do local
N2 onde “mora” o
ponteiro.
&N2[0] ?? ?? ??
&N2[0]
AED (IST/DEEC) 15
Ponteiros [4]
• Exemplo (continuação)
N2[1] = 5; N2
&N2[0] ?? 5 ??
&N2[1]
printf(“%d”, *(N2+1));
•5
• porque N2+1 é &N2[1]: quando a variável for de tipo
ponteiro para tabela, + adiciona espaço de cada célula
printf(“%d”, *N2+1);
• ??+1
• porque *N2 é o conteúdo de N2[0] que contém ??.
AED (IST/DEEC) 16
Síntese da Aula 1 de Tipologia e Operações
• Introdução aos Dados e Algoritmos
• Ponteiros
AED (IST/DEEC) 17
Tabelas [1]
• Def: Uma tabela (“array”) é uma série de localizações, todas do
mesmo tipo, acedidas por índices numéricos a partir de 0.
– Sintaxe: após a declaração base inserir uma das opções
• {[Dimensão]}+
– Restrições:
• as dimensões são inteiros positivos.
ex: int Tab1[4]; /* tabela de 4 inteiros */
char Tab2[3][2]; /* tabela de char 3 por 2 */
char Tab3[5][14][2]; /* tabela de char 5 por 14 por 2 */
AED (IST/DEEC) 18
Tabelas [2]
• Os índices são valores entre 0 e largura-1, para cada dimensão.
ex: Tab1[0]=0; /*correcto*/
Tab1[4]=-25; /*incorrecto: limite máximo é 3 */
Tab2[2][0]='?'; /*correcto*/
AED (IST/DEEC) 19
Tabelas [3]
As tabelas são inicializadas por ciclos de varrimento ou lista de
valores delimitada por { }.
ex: /* tabela Tab1 inicializada com inteiros */
– for(Idx=0; Idx<4; Idx++) Tab1[Idx]=Idx;
– Tab1 = {0,1,2,3};
/* inicialização de Tab2 */
– for(Idx1=0; Idx1<3; Idx1++)
for (Idx2=0; Idx2<2; Idx2++)
Tab2[Idx1][Idx2] = 'a'+2*Idx1+Idx2;
– Tab2 = { {'a','b'}, {'c','d'}, {'e','f'} };
AED (IST/DEEC) 20
Tabelas [4]
Em C, existe uma correspondência entre tabelas e ponteiros:
*Array ⇔ Array[0]
*(Array + 1) ⇔ Array[1]
*(Array + Idx) ⇔ Array[Idx]
As instruções seguintes:
int Array[10]; int *Ptr;
Array[2] = 3;
Ptr = Array + 2;
printf(“%d\n”, *Ptr);
escrevem 3 no terminal.
AED (IST/DEEC) 21
Tabelas [5]
Quando o tamanho da tabela é conhecido apenas na altura da
execução deve-se alocar a memória de maneira dinâmica (ver
também acetato 15):
#include <stdlib.h>
#include <stdio.h>
main (int pArgc, char *pArgv[])
{
int Numb = atoi(pArgv[1]);
int *Space = (int *) malloc(Numb * sizeof (int));
if (Space == NULL)
fprintf(stderr, “Memória insuficiente.\n”);
…
AED (IST/DEEC) 22
Tabelas multidimensionais [1]
• Declaração:
float Vect[10][20];
Declara um vector de 10 elementos, cada elemento sendo um vector de 20
elementos de float.
• Alocação dinâmica:
float ** Newmatrix(int pRows, int pColumns) {
int Idx;
float **mat; /* mat é um apontador para uma
tabela que contém float ! */
mat = (float **)malloc(pRows * sizeof (float *));
for (Idx=0; Idx<pRows; Idx++)
mat[Idx]=(float *)malloc(pColumns * sizeof(float));
return mat;
}
AED (IST/DEEC) 23
&mat[0]
&mat[0][0]
– há que fazer malloc para mat[1] e mat[2] como acima.
AED (IST/DEEC) 24
Tabelas multidimensionais [3]
• Exemplo (continuação):
– Depois de se usar a matriz “mat” pode ser necessário libertar a memória.
– Tal faz-se pela ordem inversa da alocação
– Liberta-se “mat[0]”, “mat[1]” e “mat[2]” e só depois se liberta
“mat”
– A sequência
free(mat[0]);
free(mat[1]);
free(mat[2]);
free(mat);
• para efeitos de posterior utilização de memória, produz
??
mat
AED (IST/DEEC) 25
AED (IST/DEEC) 26
Tabelas multidimensionais [5]
• Exemplo: multiplicação de matrizes:
float **Mult(float **pA, float **pB,
unsigned pLA, unsigned pCB, unsigned pS){
int IdxI,IdxJ,IdxK;
float **Res = Newmatrix(pLA,pCB);
for (IdxI=0; IdxI < pLA; IdxI++)
for (IdxJ=0; IdxJ < pCB; IdxJ++)
for (IdxK=0; IdxK < pS; IdxK++)
Res[IdxI][IdxJ] += pA[IdxI][IdxK] * pB[IdxK][IdxJ];
return(Res);}
uso da função:
#define LINEA 10
#define COLB 15
#define SIZE 20
float **ArrA = Newmatrix(LINEA,SIZE),
**ArrB = Newmatrix(SIZE,COLB), **ArrC;
ArrC = Mult(ArrA, ArrB, LINEA, COLB, SIZE);
AED (IST/DEEC) 27
AED (IST/DEEC) 28
Cadeias de caracteres [2]
• Processamento de cadeias de caracteres
Exemplo: procura numa cadeia de caracteres
AED (IST/DEEC) 29
AED (IST/DEEC) 30
Estruturas [1]
• As tabelas apenas permitem alocar, estática ou dinamicamente,
“caixas” de memória para objectos do mesmo tipo;
– Só inteiros, só reais, só caracteres...
• Para agrupar objectos de tipos diferentes numa mesma variável
existem as estruturas
– Exemplo:
#define SIZE 80
struct {
char nome[SIZE];
int idade;
float altura;
} pessoa;
Estruturas [2]
• A partir do momento que se definem estruturas, mais ou menos
complexas, podem definir-se novos tipos
– Exemplo:
• typedef struct {
char nome[SIZE];
int idade;
float altura;
} pessoa;
AED (IST/DEEC) 32
Estruturas [3]
• Uma estrutura pode ter qualquer número de campos e cada
campo pode ser qualquer um dos tipos definidos e/ou ponteiros
para esses tipos.
– struct {
int numero;
pessoa aluno;
float *notas_de_cadeiras;
} aluno_IST;
• Inclusivamente pode-se fazer o seguinte
• typedef struct _no_elementar{
unsigned int numero;
pessoa aluno;
struct _no_elementar * proximo;
} no;
AED (IST/DEEC) 33
Estruturas [4]
• Fazer
no *aed;
equivale a fazer
??
aed
• E fazer
aed = (no *) malloc(1*sizeof(no));
equivale a fazer
&aed.numero ? ? ?
AED (IST/DEEC) 34
Estruturas [5]
• E fazer
aed->proximo = (no *) malloc(1*sizeof(no));
equivale a
 ? ?  ? ? ?

aed numero aluno proximo numero aluno proximo

• Notar que qualquer campo de uma estrutura que seja um ponteiro apenas reserva
o espaço para o ponteiro aquando da alocação;
• Compete ao programador estar consciente de que tem ponteiros como campos
das estruturas. Tem de reservar posteriormente memória para guardar os objectos
apontados por esse ponteiro, assim como lembrar-se de libertar essa memória.
AED (IST/DEEC) 35
Estruturas [6]
• Como se liberta a memória dos objectos criados atrás
– Correctamente
free(aed->proximo);
free(aed);
??
aed
– Incorrectamente
free(aed);
?? ? ? ?

AED (IST/DEEC) 36
Síntese da Aula 2 de Tipologia e Operações
• Tabelas
– Unidimensionais
– Multidimensionais
– Alocação dinâmica e estática
• Cadeias de Caracteres
• Estruturas
– Conceito base e construção
– Definição de novos tipos
– Exemplos de manipulação dinâmica de memória
AED (IST/DEEC) 37
Listas [1]
• Definição: uma lista é uma sequência de nós compostos por
• um item, contendo informação específica do nó.
• um apontador para o nó seguinte.
AED (IST/DEEC) 38
Listas [2]
• Estrutura conceptual
• Disposição em memória
“head”
   NULL



AED (IST/DEEC) 39
Listas [3]
• Definição em C:
Cada nó da lista é composto por :
– Um item, que contém a informação específica ao elemento,
normalmente definido por declaração tipo:
typedef xxx Item;
– Um apontador para o próximo elemento da lista.
O último elemento da lista tem o seu campo next inicializado com NULL.
AED (IST/DEEC) 40
Listas [4]
• Declaração:
uma lista é representada por um apontador para uma estrutura de tipo list:
list *l;
• Alocação de um elemento de lista:
l = (list *) malloc(sizeof(list));
if (l == NULL) {
fprintf(stderr, “Não há mais memória...!\n”);
}
AED (IST/DEEC) 41
Listas [5]
• Acesso a informação:
list *l;
(*l).item e (*l).next permitem aceder aos dois campos da
estrutura.
Mais simplesmente, podemos usar o operador -> e escrever:
l->item, l->next
AED (IST/DEEC) 42
Tabela de listas
• Como se cria uma tabela de listas?
list **tlst;
tlst = (list **) malloc(4*sizeof(list *));
tlst
&tlst[0] ?? ?? ?? ??
&tlst[0]
&tlst[1]
&tlst[2]
&tlst[3]
lst_lst *exemplo;
AED (IST/DEEC) 44
Lista de listas [2]
• A instrução
lst_lst * exemplo;
produz apenas
exemplo
??
• E as instruções
exemplo = (lst_lst *) malloc(sizeof(lst_lst));
exemplo->seguinte = NULL;
produzem
exemplo
 ?? 00...00

lista seguinte
AED (IST/DEEC) 45

AED (IST/DEEC) 47

AED (IST/DEEC) 48
Listas duplamente ligadas [1]
• Para criar uma lista com ponteiros para a frente e para trás
(anel)
typedef struct _d_lst_ {
Item objecto;
struct _d_lst_ * anterior;
struct _d_lst_ * posterior;
} dlst;
dlst * frente_verso;
frente_verso = (dlst *) malloc(sizeof(dlst));
frente_verso->anterior = frente_verso->posterior = NULL;
frente_verso
 ?? 00...00 00...00
AED (IST/DEEC) 49
frente_verso
 ?? 00...00  ??  00...00
AED (IST/DEEC) 50
Interface para Listas [1]
• A interface do tipo list, é constituída por:
– A definição do tipo list:
#include “defs.h” Ficheiro que define item
typedef struct _list {
Item item;
struct _list *next;
} list;
– Alocação de um novo elemento:
list * NewElement(Item);
– Libertação da memória associada a um elemento:
void FreeElement(list *);
AED (IST/DEEC) 51
AED (IST/DEEC) 52
Interface para Listas [3]
• No ficheiro “defs.h” define-se o item, por exemplo
AED (IST/DEEC) 53
AED (IST/DEEC) 54
Implementação para Listas [2]
– Inserção de um elemento a seguir a outro:
void InsertNext(list *pEl1, list *pEl2) {
pEl1->next = pEl2->next;
pEl2->next = pEl1;
}
etc..
pEl2
pEl1
etc..
pEl2 primeiro!
depois!
pEl1
AED (IST/DEEC) 55
pEl aux
depois!
pEl
primeiro!
AED (IST/DEEC) 56
Implementação para Listas [4]
– Função para aceder ao elemento seguinte:
list * Next (list *pEl) {
return pEl->next;
}
AED (IST/DEEC) 57
AED (IST/DEEC) 58
Implementação para Listas [6]
• Função para reverter uma lista:
list *reverse (list *pL) {
list *Next = pL, *Cur = pL, *Res = NULL;
while (Cur != NULL) {
Next = Cur->next;
Cur ->next = Res;
Res = Cur; Cur = Next;
}
return Res;
}
AED (IST/DEEC) 59
AED (IST/DEEC) 60