• Nenhum resultado encontrado

Listas Ligadas em C. Aula 14 ED

N/A
N/A
Protected

Academic year: 2021

Share "Listas Ligadas em C. Aula 14 ED"

Copied!
24
0
0

Texto

(1)

Listas Ligadas em C

(2)

Alocando e liberando variáveis

dinâmicas



Se x é um objeto qualquer

 &x é um ponteiro para x



Se p é um ponteiro em C

 *p é o objeto apontado por p



Podemos usar os ponteiros de C para

(3)

Alocando e liberando variáveis

dinâmicas

 Uma variável ponteiro para inteiro pode ser criada

 int *p;

 Se uma variável p for declarada como um ponteiro para um tipo de objeto específico será possível criar dinamicamente um objeto desse tipo em específico e atribuir seu endereço a p. Isso pode ser feito usando a bib. padrão

 malloc(size) : Aloca dinamicamente um parte da

memória de tamanho size e retorna um ponteiro para um item de tipo char (No C original no padrão atual devolve um ponteiro a void)

(4)

Exemplo

 Declarações

 int *pi;  float *pr;

 Comandos

 pi = (int *) malloc(sizeof (int))

 pr = (float *) malloc(sizeof (float))

 Criação das variáveis dinâmicas *pi (inteira) e *pf (flutuante). (type *) força o ponteiro a indicar o tipo a que deve apontar

(5)

Exercício

int *p, *q; int x;

p = (int *) malloc(sizeof (int)); *p = 3; q = p; printf (“%d %d\n”, *p, *q); x = 7; *q = x; printf(“%d %d\n”, *p, *q);

p = (int *) malloc(sizeof (int)); *p = 5;

printf(“%d %d\n”, *p, *q);

3 3

7 7

5 7

(6)

Alocando e liberando variáveis

dinâmicas



Função free usada em C para liberar o

armazenamento de uma variável alocada

dinamicamente

 free(p); (invalida quais quer referencias

futuras a *p. A chamada desta função torna o armazenamento ocupado por *p disponível para reutilização, a função recebe um ponteiro)

(7)

Exercício

int *p, *q;

p = (int *) malloc(sizeof (int)); *p = 5;

q = (int *) malloc(sizeof (int)); *q = 8;

free(p); p = q;

q = (int *) malloc(sizeof (int)); *q = 6;

printf(“%d %d\n”, *p, *q);

(8)

Observe detidamente

int *p;

p = (int *) malloc(sizeof (int)); *p = 3;

p = (int *) malloc(sizeof (int)); *p = 7;

Nesse caso a primeira cópia de p é perdida e seu conteúdo não pode ser liberado porque o endereço não foi salvo

(9)

O valor NULL



NULL indica um ponteiro que não aponta a

nada



O valor 0 (zero) pode ser definido como

NULL

 #define NULL 0



O valor NULL (zero) pode ser atribuído a

qualquer variável ponteiro p, após o que a

referencia *p é inválida

(10)

Tome cuidado!!

 Uma chamada a free(p) invalida uma referencia subseqüente a *p entretanto os verdadeiros efeitos de free não são definidos pela linguagem C, cada implementação de C pode desenvolver sua própria versão dessa função. Na maioria das implementação e o armazenamento *p é liberado mais o valor de p fica inalterado. Isso significa que embora uma referencia para *p se torne inválida talvez não exista um meio de detectar a invalidação. O valor de p é um endereço válido objeto nesse endereço, de tipo correto, pode ser usado como valor de *p . p é chamado de ponteiro perdido. E responsabilidade do programador jamais usar esse ponteiro num programa. Convém explicitamente definir p como NULL depois de executar free(p).

•Se p e q são ponteiros com o mesmo valor, as variáveis *p e

*q são idênticas. *p e *q referem-se ao mesmo objeto. Uma

(11)

Listas Ligadas usando variáveis

dinâmicas

 Para implementar listas ligadas o primeiro é fazer os nós.

Definiremos os nos como

struct node { int info;

struct node *next;

};

typedef struct node *NODEPTR;

 info: Campo de informação

 node: ponteiro para o próximo nó na lista  *NODEPTR: Ponteiro a estrutura node

(12)

Listas Ligadas usando variáveis

dinâmicas

Com essa implementação do nó se declaramos

NODEPTR p;

o comando

p = getnode();

deverá colocar o endereço de um nó disponível em p

NODEPTR getnode(){ NODEPTR p;

p = (NODEPTR) malloc(sizeof(struct node)); return p;}

e o comando

freenode(p);

Deve disponibilizar o nó que está apontado por p void freenode(NODEPTR p) {free(p);}

(13)



Note que:

 O programador não deverá preocupar se com o

ponteiro avail apontando para o primeiro nó disponível uma vez que os sistema de alocação rastreia esse nó

 Não existe nenhum teste em getnode para

determinar a ocorrência de estouro essa condição é detectada no malloc e depende do sistema.

(14)

Operações primitivas da lista



insafter: Aceita um ponteiro p para um nó e

um item x como parâmetros. Insere x no

siguinte nó apontado por p



deleafter: Aceita um ponteiro a um nó e um

ponteiro a um item x como parâmetros.

Elimina o nó seguinte a node(p) e armazena

seu conteúdo em x

(15)

Operações primitivas das listas ligadas

void insafter (NODEPTR p, int x) { NODEPTR q; if (p == NULL) { printf(“inser. nula”); exit(1); } q = getnode(); q->info = x; q->next = p->next; p->next = q; } void deleafter (NODEPTR p,int *px) { NODEPTR q; if((p==NULL)||(p->next==NULL)) { printf(“remoção nula”); exit(1); } q = p->next; *px = q->info; p->next = q->next; freenode(q); }

(16)

FILAS como LISTAS em C

 Suponhamos que a struct node e NODEPTR

tenham sido declaradas struct fila {

NODEPTR inicio, fim; };

struct fila q;

 Inicio e fim são ponteiros ao primeiro e último nó de uma fila representada como uma lista. Como seria empty?

(17)

int empty(struct fila *pq) { return ((pq->inicio == NULL)? 1: 0); } void insert

(struct fila *pq, int x) { NODEPTR p; p = getnode(); p->info = x; p->next = NULL; if (pq->fim == NULL) pq->inicio = p; else (pq->fim)->next = p; pq->fim = p; }

int remove(struct fila *pq) { NODEPTR p; int x; if (empty(pq)) { printf(“underflow\n”); exit(1); } p = pq->front; x = p->info; pq->fornt = p->next; if (pq->front == NULL) pq->rear = NULL; freenode(p); return(x); }

(18)

Outras operações com Listas em C

 Definamos a operação place(list, x) list aponta a uma

lista linear classificada e x um elemento a ser inserido em sua posição correto na lista, operação usada para implementar o pqinsert

void place(NODPTR *plist, int x){ NODEPTR p, q;

q = NULL;

for(p = *plist; p!=NULL && x>p->info; p = p->next) q = p;

if(q == NULL) push(plist, x);//ins. x no ini lista else insafter(q, x);}

 plist deve ser declarada como um ponteiro para o ponteiro da

lista uma vez que o valor do ponteiro de lista externo será alterado si x for inserido no inicio da lista usando o push. A chamada a essa rotina será place(&list, x)

(19)

Outras operações com Listas em C



Definamos insend: Insire um elemento no

final da lista

void insend(NODPTR *plist, int x){ NODEPTR p, q;

p = getnode(); p->info = x;

p->next = NULL;

if(*plist == NULL) *plist p; else { //procura o ultimo nó

for(q=*plist; q->next!=NULL; q=q->next); q->next =p;}

(20)

Outras operações com Listas em C



Função search(list, x) retorna um ponteiro

para a primeira ocorrência de x dentro de

uma lista list e o ponteiro NULL se x não

ocorrer na lista

NODEPTR search(NODPTR *plist, int x){ NODEPTR p;

for(p=plist; p!=NULL; p=p->next) if (p->info == x) return (p); return (NULL);

(21)

Listas lineares não homogêneas

 Evidentemente um nó numa lista não precisa representar um inteiro, para representar uma pilha de strings de caracteres por uma lista ligada, são necessários nós contendo as strings de carateres em seus campos info. Os nós poderiam ser:

struct node{

char info[100];

struct node *next; };

(22)

Listas lineares não homogêneas

 É possível que determinadas aplicações exija nós mais de um item na informação. Exemplo um nó de estudante: struct node { char name[30]; char id[9]; char address[100]; float gpindex; char major[20];

struct node *next; };

(23)

Listas lineares não homogêneas

 Também podemos representar listas não homogêneas: Que contem

nós de diversos tipos. Neste caso é um nó cujos itens podem ser de 3 tipos. Uma união sempre faz os nós o suficiente grande , se usa um malloc para a união pegará o espaço para o maior dos elementos e getnode e freenode não precisarão ser reformadas

#define INTGR 1 #define FLT 2 #define STRING 3 struct node{ int etype union{ int ival; float fval; char *pval; } element;

struct node *next; };

(24)

Implementação de nós cabeçalhos

 Lembrando... Nós cabeçalhos são usados para conter informações globais sobre a lista. Se o conteúdo desse nó é igual ao resto o cabeçalho pode ser implementado como os outros. Porem podem ser diferentes

struct node{ char info;

struct node *next; };

struct charstr{ int legth;

struct node *firstchar; };

struct charstr s1, s2;

 s1 e s2 do tipo charstr são nós cabeçalhos para uma lista de

caracteres. O cabeçalho contem o número de caracteres na lista e um ponteiro para a lista firstchar. s1 e s2 representam

Referências

Documentos relacionados

- Remover as pastilhas usadas e retornar todo o parafuso de regulagem em seguida montar uma pastilha nova do lado da roda, empurrando com a mão a pinça no sentido do cilindro de

Podem treinar tropas (fornecidas pelo cliente) ou levá-las para combate. Geralmente, organizam-se de forma ad-hoc, que respondem a solicitações de Estados; 2)

Arrendatários e parceiros são mais prósperos e mais bem educados nas regiões onde a cultura da cana está concentrada, e existe uma correlação entre mercados de aluguel ativos e

calloc retorna um ponteiro para um array com n elementos de tamanho size cada um ou NULL se não houver memória disponível. Os

O Produto 5 seguirá um modelo a ser disponibilizado pela Comissão de Seleção e consistirá na síntese dos Produtos 1 a 4, levando-se em consideração o escopo

autoria de pensamento, compreendendo o(a) aprendente em movimento, em busca de significados e sentidos para as suas práticas. Para entender melhor os processos de

Em sua fase de construção, foram elaborados 28 itens para representar contentamento no trabalho a partir de seis dimensões: satisfação com o salário (cinco itens), satisfação com

Feitiço do Segredo: deposita um segredo numa pessoa de confiança, essa pessoa fica deposita um segredo numa pessoa de confiança, essa pessoa fica sendo o "Fiel do sendo o