Professora Jeane Melo Roteiro Lista Encadeada Alocação: Estática x Dinâmica O que são Ponteiros? Ponteiros Variáveis que Armazenam Endereços de Memória Mas, toda variável não é armazenada na memória? Ponteiros Toda variável é armazenada na memória. Mas, os ponteiros armazenam variáveis que armazenam o endereço de memória. Variáveis são armazenadas na memória(gavetas) As gavetas possuem uma localização, endereço. Ponteiros apontam para o ENDEREÇO da Memória (Ponteiros “sabem” em que gaveta está a variável) Ponteiros Variável Comum Ponteiros O conteúdo é um valor (instâncias de um determinado tipo) Ao atribuirmos um valor modificamos apenas o conteúdo da variável atual Referência: indica um endereço na memória Ao modificarmos o valor armazenado naquela referência alteramos os valores das variáveis que apontam para ela. Ponteiros Em C/C++ Por default, as variáveis armazenam valores Criar ponteiros explicitamente Em Java Tipos primitivos armazenam valores Tipos compostos (classes) armazenam referências Alocação Estática Quantidade Memória Prédefinida. Conteúdo armazenados em endereços estáticos. Exemplo: var num: integer; Num := 5; Alocação Dinâmica Alocação de memória feita em tempo de Qual a relação de Alocação Dinâmica de execução memória e Ponteiros? Alocação Dinâmica Ponteiros “sabem” em que gaveta está a variável. malloc O comando “escolhe” em que gaveta será guardada a variável que armazena o ENDEREÇO de memória. Endereços e Ponteiros Variáveis char c; int i; struct { int x, y; } ponto; int v[4]; Endereços (fictícios) c 89421 i 89422 ponto 89426 v[0] 89434 v[1] 89438 v[2] 89442 v[3] 89446 Se i é uma variável &i é seu endereço Endereços e Ponteiros Ponteiro Tipo especial de variável que armazena endereços NULL Se p armazena o endereço de i, então *p é o valor do objeto apontado por p (*p=i) Para declarar um ponteiro para um inteiro em C usamos: int *p Endereços e Ponteiros Para usarmos as funções relacionadas com alocação dinâmica em C (malloc e free), precisamos incluir a biblioteca stdlib no início do programa: #include <stdlib.h> A função malloc (abreviatura de memory allocation) aloca um bloco de bytes consecutivos na memória do computador e devolve o endereço desse bloco A função free libera a porção de memória alocada por malloc Alocação Dinâmica A memória é alocada no momento em que é requisitada. C e Java possuem comandos para alocação de memória (“criar as caixinhas”) Java: Ponto p = new Ponto(800,600); C: struct Ponto *p; p = (struct Ponto *) malloc(sizeof(struct Ponto)); Alocação Dinâmica Em C, precisamos liberar o espaço alocado para uma variável antes de eliminar uma referência para esta. Para isto utilizamos o comando “free”: free(p) Em Java, não é necessário tal operação, esta é realizada a cada garbage collection Alocação Estática X Dinâmica Estática – A quantidade de memória é definida previamente e não muda durante a execução do programa. Alocação consecutiva Acesso direto Não permite a adição de elementos durante a execução (dinamicamente) Alocação Estática X Dinâmica Dinâmica A quantidade de memória utilizada pelo programa pode variar durante a execução do mesmo. Cada elemento é representado separadamente Os elementos são conectados através de ponteiros Flexibilidade Mais espaço Não é possível acessar um elemento diretamente Alocação Estática X Dinâmica Estática Acesso direto Inserção e remoção no final da lista Inserção e remoção no meio da lista Dinâmica O acesso não é direto Inserção e remoção de elementos Memória adicional para armazenar os ponteiros Lista Encadeada Listas Posição relativa dos elementos Os elementos são dispostos linearmente a1 a2 a3 ... an a1 - primeiro elemento an - último elemento O elemento ai , é precedido do elemento ai-1 e seguido do elemento ai+1 Lista Encadeada Operações comuns Busca Inserção Remoção Substituição Outras operações Ordenação, União, Particionamento, Determinação do total de elementos. Lista Encadeada Listas Arrays Encadeamento Pilhas, Filas Listas Encadeadas Lista Encadeada Exemplo mais simples de alocação dinâmica Lista de pares (armazenam uma quantidade variável de elementos do mesmo tipo) Cada par é representado por um registro que consiste de um elemento e de um endereço Normalmente contém uma referência para o 1o nó da lista Lista Lista elemento prox elemento prox elemento NULL prox elemento prox NULL Lista Encadeada Usando OO (java) A lista é composta por células (ou nós) Cada célula (ou nó) possui um Objeto (info) e um apontador(next) para um o próximo elemento da lista class Node { int valor; Node next; } Lista Encadeada O último nó da lista não aponta para lugar nenhum (null). public Node (int valor) { this.valor = valor; this.next = null; } Lista Encadeada Classe Lista class Lista { Node inicio; public Lista() { this.inicio = null; } //Acrescentamos as operações associadas public void inserir(int valor) {...} } Lista Encadeada Criar uma classe Nó (ou Node) com dois atributos: um para guardar um objeto(info) e outro para guardar uma referência ao próximo nó da lista. Criar uma classe que represente uma lista encadeada Nesta classe teremos um nó que representa o início da lista (denominado cabeça) Para as operações de inserção, verificamos se a lista está vazia. Lista Encadeada sequência de células cada célula contém um objeto de algum tipo e o endereço da célula seguinte Supondo que os objetos são do tipo int (Em C: ) struct cel { int conteudo; struct cel *prox; Conteudo Prox }; typedef struct cel celula; //tratar como um novo tipo de dados Lista Encadeada celula c; // declaração de uma célula celula *p; // declaração de um ponteiro para célula c.conteudo //conteúdo da célula c.prox // endereço da próxima célula p->conteudo // conteudo da celula p->prox //endereço da próxima celula Lista Encadeada // criando uma lista celula *ini; ini = malloc (sizeof (celula)); ini->prox = NULL; //imprimindo uma lista void imprima (celula *ini) { celula *p; for (p = ini->prox; p != NULL; p = p->prox) printf ("%d\n", p->conteudo); } Lista Encadeada void insere (int x, celula *p) { celula *nova; nova = malloc (sizeof (celula)); nova->conteudo = x; nova->prox = p->prox; p->prox = nova; } Lista Encadeada Insere p elto1 prox elto2 Após inserção prox NULL X p prox X prox elto1 prox elto2 prox NULL Lista Encadeada //buscar um elemento x em uma lista encadeada celula *busca (int x, celula *ini) { celula *p; p = ini->prox; while (p != NULL && p->conteudo != x) p = p->prox; return p; } Lista Encadeada void remove (celula *p) { celula *morta; morta = p->prox; p->prox = morta->prox; free (morta); } Lista Encadeada void buscaEremove (int y, celula *ini) { celula *p, *q; p = ini; q = ini->prox; while (q != NULL && q->conteudo != y) { p = q; q = q->prox; } if (q != NULL) { p->prox = q->prox; free (q); } } Lista Encadeada P elemento prox elemento prox elemento prox NULL P MORTA elemento prox elemento prox elemento prox NULL Lista Encadeada Outros tipos de Lista Circular Duplamente encadeada Lista Circular Lista elemento prox elemento prox elemento prox NULL Lista elemento prox elemento prox elemento prox Lista Duplamente Encadeada Cada celula passa a ter três campos: elemento – o conteúdo propriamente dito prox – endereço da próxima célula ant – endereço da célula anterior Lista Duplamente Encadeada Lista ant elemento prox ant elemento prox ant elemento prox NULL Exercício Implemente a lista encadeada em Java ou C Faça uma apresentação (ppt) sobre a sua implementação Entrega: Sexta-feira 13/05 (impresso Código + apresentação) Referências Capítulo 10 - Cormen Lista encadeada (Paulo Feofiloff - IME-USP) http://www.ime.usp.br/~pf/algoritmos/aulas/lista.html