29
Listas Encadeadas

Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Embed Size (px)

Citation preview

Page 1: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Listas Encadeadas

Page 2: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista encadeada: É uma coleção linear de objetos auto-referenciados de classe, chamados nós, conectados por links de referência. Em geral um programa acessa uma lista via uma referência ao primeiro item da lista. O programa acessa cada link subseqüente via a referência de link armazenada no nó anterior. A referência do último nó é marcada como null (terra) para marcar o fim da lista. Dados são armazenados em uma lista encadeada dinamicamente, o programa cria cada nó conforme o necessário. Um nó pode conter dados de qualquer tipo, inclusive uma referência a objetos de outra classe.

Vantagens de listas encadeadas X arrays: - Listas encadeadas são dinâmicas, portanto seu tamanho pode

aumentar ou diminuir conforme o necessário. - Lista encadeadas podem ser mantidas em ordem de classificação

simplesmente inserindo cada elemento no ponto adequado da lista (a demora vai ser achar este ponto) não precisa mover os outros elementos da lista, (apenas duas referências são mudadas).

- Nós de lista encadeada não estão armazenados contiguamente na memória, são apenas logicamente contíguos.

Page 3: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Listas simplesmente encadeadas: Uma lista é denominada simplesmente encadeada se em cada nó só existe um ponteiro que aponta para o próximo nó, cuja representação é feita da seguinte maneira:

Em listas simplesmente encadeadas trabalhamos com alocação dinâmica de memória que já é a forma natural do Java trabalhar. O limite da alocação dinâmica de memória é igual ao espaço disponível em memória física + o disponível em mem. virtual (normalmente menor que isto pois estas memórias são compartilhadas por diversos aplicativos). É interessante lembrarmos que em Java não precisamos liberar explicitamente a memória alocada uma vez que ele próprio já faz a coleta automática de lixo.

Page 4: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Vejamos as operações mais básicas em uma lista encadeada: Lista com um elemento:

Inserir um nó na frente da lista:

Page 5: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Inserir nó no final da lista Remover nó da frente da lista Inserir nó após determinado nó passado

como parâmetro Remover nó após determinado nó

passado como parâmetro Inserir no fim da lista

Page 6: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Continuando lista encadeada iremos agora procurar determinado elemento na lista: Dado uma chave faça um método que retorne um ponteiro para

o nó que contém o elemento procurado. Uma vez que estamos usando Strings como elementos

devemos ver algumas características da classe String. Comparar o conteúdo de dois Strings com == não vai funcionar; Para verificar se o conteúdo de dois Strings é o mesmo usa-se o

método equals de String. Ex:

String nome, nome2;...If (nome.equals(nome2))

System.out.println(“São iguais!”)else

System.out.println(“São diferentes!”);

Page 7: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Agora que já vimos um pouco sobre comparações de Strings faça o método:Dado uma chave faça um método que retorne

um ponteiro para o nó que contém o elemento procurado.

Page 8: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Para verificar qual de dois Strings é o maior usa-se compareTo. Ex:String nome, nome2;

...

if (nome.compareTo(nome2) > 0)

System.out.println(nome+” é maior que “+nome2);

else if (nome.compareTo(nome2) < 0)

System.out.println(nome+” é menor que “+nome2);

else

System.out.println(“São iguais”);

compareTo retorna 0 se as Strings forem iguais < 0 se a string que invoca for menor que a passada como arg. > 0 se a string que invoca for maior que a passada como arg.

Page 9: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Agora que já vimos um pouco sobre comparações de Strings faça o método: Faça um método que dada uma chave insira um nó

na lista de forma ordenada. Procurar local onde vai inserir Guardar nó anterior ao ponto da inserção Inserir após o anterior que foi guardado (insereAposAtual) Verificar se o nó inserido não seria o primeiro da lista (neste

caso vai ser chamado insereNaFrente)

Dado uma chave faça um método que remova o nó que contém o elemento procurado.

Page 10: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Análise dos algoritmos: A inserção e a remoção no início da lista encadeada

é muito rápido uma vez que o número de operações é fixo e independe do tamanho da lista, sendo a ordem O(1).

A busca, remoção e a inserção após um item específico precisam percorrer, em média, até a metade da lista, sendo a ordem O(N). Nas listas seqüenciais essas operações também têm ordem O(N), mas nas listas encadeadas a inclusão e a remoção são bem mais rápidas uma vez que não será necessário mover os itens para abrir vaga para inserir um item ou para ocupar a vaga do item removido.

Page 11: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Listas com nó cabeça

Algumas implementações de listas encadeadas costumam manter um nó cabeça. A informação contida neste nó não representa nenhum ítem da lista, ele pode ser usado para conter informações gerais da lista como o número de nós e etc.

Page 12: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Exercício Com base no programa anteriormente feito crie uma

classe que seja uma lista com nó cabeça, onde na cabeça seja registrada a quantidade de nós que estão na lista a cada momento. Crie um método ou classe que demonstre a utilização desta lista.

Obs: A cabeça não entra na contagem da quantidade de nós. O nó firstNode agora vai estar dentro do nó cabeça.

Page 13: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Circular Em uma lista circular o último nó da lista aponta para o

primeiro. Nesta lista não se guarda o endereço do primeiro e do

último nó da lista, guarda-se o endereço de somente um deles.

Neste tipo de lista é possível acessar qualquer nó a partir de qualquer ponto, pois na verdade poderíamos considerar qualquer nó como sendo o primeiro.

Na implementação deste tipo de lista é interessante que o ponteiro para a lista aponte para o nó final, e não para o primeiro, pois a partir do nó final poderemos acessar facilmente o primeiro nó da lista.

As operações em uma lista circular são semelhantes as operações em uma lista comum, devemos apenas ter cuidado nas operações que envolvem o nó inicial e o nó terminal.

Page 14: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Circular Vejamos como seria inserir um nó no início da

lista:

Page 15: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Circular Código para inserção de nó á frente de lista circular:

public void insereNaFrente(String n) { if (estaVazia()) { listaNode = new Node(n); listaNode.proxNode = listaNode; } else listaNode.proxNode = new Node(n,listaNode.proxNode);

}

Page 16: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Circular Código para remoção de nó da frente da lista circular

public Object removeDaFrente() { if (estaVazia()) { System.out.println("Lista "+nomeLista+" se encontra vazia"); return null; } Object removido = listaNode.proxNode.data; if (listaNode == listaNode.proxNode) listaNode = null; else listaNode.proxNode = listaNode.proxNode.proxNode; return removido; }

Page 17: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Circular Código para inserção de nó ao final da lista circular

public void insereNoFim(String n) { if (estaVazia()) { listaNode = new Node(n); listaNode.proxNode = listaNode; } else { listaNode.proxNode = new Node(n,listaNode.proxNode); listaNode = listaNode.proxNode; } }

Page 18: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Duplamente Encadeada Para uma maior flexibilidade na manipulação de listas

lineares, podemos incluir dois ponteiros em cada nó, um para apontar para o próximo nó e o outro para apontar para o nó anterior, como mostrado na seguinte figura:

Page 19: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Duplamente Encadeada A classe nó para uma lista duplamente encadeada seria:

class Node{ Object dado; Node proxNode; Node ant; //Construtor principal, cria um nó e o liga a um anterior e um próximo Node(Object d, Node anterior, Node proximo) { dado = d; ant = anterior; proxNode = proximo; } //Construtor para um último nó, na verdade chama o de três Node(Object d) { this(n,null,null); }}

Page 20: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Duplamente Encadeada Como adicionamos mais um ponteiro no nó, uma lista

duplamente encadeada ocupa mais espaço que uma lista simplesmente encadeada. No entanto, a vantagem que temos em poder percorrer a lista nas duas direções compensa a memória extra que utilizamos. Além disso, agora podemos excluir qualquer nó conhecendo apenas o ponteiro que aponta para ele.

Vejamos como seriam algumas rotinas em lista duplamente encadeada: Inserir nó no início da lista

Page 21: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Duplamente Encadeada

Page 22: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Duplamente Encadeada

Rotina que insere um nó após o nó corrente.

public void insereAposAtual(Node atual,Object n) { if (estaVazia()) primNode = ultiNode = new Node(n); else { atual.proxNode = new Node(n,atual,atual.proxNode); if (atual == ultiNode) ultiNode = ultiNode.proxNode; else atual.proxNode.proxNode.ant = atual.proxNode; } }

Page 23: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Lista Duplamente Encadeada

Rotina que remove o primeiro nó da lista. Rotina que remove o nó corrente.

Page 24: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Multilista Uma estrutura na qual um nó aparece em mais de uma lista e contém

mais de um ponteiro é denominada de lista multiencadeada ou multilista. Uma lista duplamente encadeada é um exemplo de multilista.

Como outro exemplo de multilista, suponha que desejamos armazenar a relação de disciplinas oferecidas por uma escola e, para cada disciplina, desejamos armazenar os alunos que estão matriculados. Para as disciplinas iremos armazenar o código e o nome da disciplina e para os alunos iremos armazenar o número de matrícula e o seu nome. A seguinte figura representa a estrutura que nós queremos:

Page 25: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Multilista

Page 26: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Multilista

Page 27: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Abrindo aspas – Números aleatórios

Para introduzir o elemento sorte em nossos programas podemos usar um gerador de números aleatórios fornecido, em Java, pela classe Random do pacote java.util. Esta classe pode gerar valores aleatórios dos tipos, int, double, boolean, byte e float. Um novo objeto gerador de números aleatórios pode ser criado como a seguir: Random numAleatorio = new Random( );

Podemos então gerar um inteiro aleatório da seguinte forma: int num = numAleatorio.nextInt( );

A chamada acima gera valores aleatórios no intervalo de -2.147.483.648 a 2.147.483.647. Se quisermos determinar uma faixa de valores podemos usar passar um inteiro para uma segunda versão de nextInt onde ele irá retornar um número que pode ir de 0 até o argumento -1.

Page 28: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Exercício – Entrega próxima aula (pode ser em dupla) Considere o seguinte problema que pode ser resolvido de uma forma

bastante elegante usando uma lista circular. Esse problema é conhecido como problema de Josephus. A seguir apresentamos uma versão do problema.

Um agente de viagem selecionou n clientes para participar de uma competição para ver que ganharia um cruzeiro em volta do mundo. O agente colocou os clientes em um círculo e sorteou um número m, sendo m <= n. Começando com o nome de um dos participantes, o agente conta no sentido horário em torno do círculo. Quando a contagem atingir o número m, o participante é removido do círculo e a contagem recomeça a partir do próximo participante. O último participante que for removido ganhará a competição.

Faça um programa em Java que usando uma lista circular implemente o problema de Josephus. Leia os nomes dos participantes do cruzeiro e vá realizando os sorteios a cada sorteio o nome do eliminado deve ser mostrado bem como os participantes que continuam concorrendo.

Page 29: Listas Encadeadas. Lista encadeada: É uma coleção linear de objetos auto- referenciados de classe, chamados nós, conectados por links de referência. Em

Trabalho (em dupla) Gerenciamento de histórico de aluno

usando multilista

Cada aluno aponta para o próximo aluno Aluno tem nome e matrícula

Cada aluno aponta para uma lista de disciplinas que já cursou

Cada disciplina tem nota, presença, situação, ano e período cursado

Situação pode ser: AP, RM, RF, TR

Entrega: 30/11/2010