4 - Facom

Propaganda
5. Implementação de Listas Lineares usando Alocação Estática e Acesso Encadeado
Uma lista estática encadeada pode ser implementada através de um vetor com dois campos,
um que contém a informação e outro que encadeia os elementos da lista. Como exemplo,
considere a lista abaixo:
inicio
da lista
0
1
a1
3
2
3
a2
4
4
a3
-1
5
No caso da lista encadeada é necessário um ponteiro que explicitamente indique o inicio da
lista.
Após sucessivas inserções e remoções como saber quais nós da lista estão disponíveis?
Uma solução é agrupá-los em uma lista de nós livres
inicio
da lista
0
2
1
a1
3
2
5
3
a2
4
4
a3
-1
5
-1
lista de livres
Vantagens:
 não requer mais a movimentação de elementos na inserção e eliminação (como na
lista sequencial);
 apenas os ponteiros são alterados (lembre que cada campo de informação do nó
pode conter elementos muito complexos);
Desvantagens:
 necessário prever espaço máximo da lista (tamanho máximo pré-definido);
 necessário gerenciar a lista de nós livres;
 o acesso é não indexado, para acessar a(i) temos que percorrer a(1) ... a(i-1) pois o
endereço de a(i) está disponível apenas em a(i-1);
 gasto maior de espaço de memória;
Quando usar:
 quando for possível fazer uma boa previsão do espaço e quando o ganho dos
movimentos sobre a perda do acesso direto a cada elemento for compensador.
5.1 Implementação do TDA lista_não_ordenada
Nesta seção implementaremos o TDA lista_não _ordenada, definida na seção 3.1, usando
alocação estática e acesso encadeado.
a) estrutura da lista: é necessário definir explicitamente um ponteiro para o inicio da lista,
um ponteiro para a lista de nós livres além de um vetor com dois campos, um para
conter a informação e outro para conter os ponteiros.
inicio
da lista
0
2
1
a1
3
2
5
3
a2
4
4
a3
-1
5
-1
lista de livres
define estrutura NO_ENC como
um inteiro que representa o elemento da lista;
um inteiro que representa um ponteiro;
fim;
define estrutura LISTA_ENC como
vetor de elementos itens do tipo NO_ENC com MAX posições;
um inteiro que indica inicio-da-lista
um inteiro que indica lista-de-livres
fim;
b) Inicializar_Lista - esta função deve garantir que a lista esteja vazia. Neste caso inicioda-lista deve apontar para um endereço inválido e todos os nós da lista estão livres.
inicio-da-lista = -1
0
1
lista-de-livres
1
2
2
3
3
4
5
4
5
-1
Inicializar_Lista (endereço da lista)
inicio
atribua -1 à variável inicio-da-lista;
atribua 0 à variável lista-de-livres;
para i variando de 0 até MAX-2
atribua ao campo de ponteiro de itens[i] o valo de i+1;
atribua ao campo de ponteiro de itens[MAX-1] o valor -1
fim;
c) Lista_É_Vazia
Uma lista está vazia se inicio-da-lista aponta para uma posição inválida.
tipo Lista_É_Vazia(endereço da lista)
inicio
se inicio-da-lista é inválido
então a função retorna True
senão a função retorna False;
fim;
d) Lista_É_Cheia
Uma lista está cheia se não há nós livres, isto é, se lista-de-livres aponta para uma posição
inválida.
tipo Lista_É_Cheia (endereço da lista)
inicio
se lista-de-livres é inválido
então a função retorna True
senão a função retorna False;
fim;
e) Insere_Elem
A inserção de um elemento em uma lista estática/encadeada é um pouco mais elaborada
que em uma lista estática/sequencial. Neste caso é necessário saber se há nó livre e qual é a
posição deste nó. O elemento será inserido na lista nesta posição. Tanto os ponteiro da lista
de elementos quanto da lista de livres precisam ser atualizados para refletir as
modificações. Considere a seguinte lista:
inicio-da-lista = 2
lista-de-livres =0
0
1
1
3
2
23
4
3
5
4
10
-1
5
-1
Suponha que queiramos inserir o elemento com valor 8. Para executar esta inserção
precisamos encontrar um nó livre. O nó livre mais fácil de ser obtido é justamente o
apontado por lista-de-livres. Sendo assim, o elemento será inserido na posição 0 do vetor.
inicio-da-lista = 2
lista-de-livres =0
0
1
1
3
2
23
4
3
5
4
10
-1
5
-1
Agora é necessário inserir o elemento no nó escolhido e atualizar as listas de livre e de
dados. Note que a inserção ocorreu no inicio da lista (cabeça da lista), diferente da alocação
estática/sequencial em que a inserção ocorria no final da lista.
inicio-da-lista = 0
lista-de-livres = 1
0
8
2
1
3
2
23
4
3
5
4
10
-1
5
-1
Algoritmo
inteiro Insere_Elem (endereço da lista, elemento a ser inserido)
inicio
se lista está cheia
então a função retorna o valor -1
senão inicio
atribi a uma variável pos o valor de lista-de-livres;
insere o elemento na posição apontada por lista-de-livres;
atualiza a variável lista-de-livres com o conteúdo do campo de ponteiros do
nó apontado por lista-de-livres;
atribui ao campo de ponteiros do nó pos o valor de inicio-da-lista;
atribui à variável inicio-da-lista o endereço do nó pos;
fim;
fim;
f) Remove_Elem
Para remover um elemento, a sua posição deve ser localizada na lista. Mas não basta
localizar o nó onde o elemento se encontra, é preciso saber também quem o antecede na
lista para que a remoção possa ser realizada com sucesso. Podemos destacar três casos:
 caso 1: lista é vazia
Neste caso não é possível remover o elemento desejado;
 caso 2: o elemento a ser removido está no inicio da lista.
Neste caso a remoção é simples. Como exemplo considere a seguinte lista:
inicio-da-lista = 0
lista-de-livres = 1
0
8
2
1
3
2
23
4
3
-1
4
10
5
5
3
-1
Suponha que queiramos remover o elemento 8, que está no primeiro nó da lista. Neste caso,
basta atualizar as variáveis inicio-da-lista e lista-de-livres.
inicio-da-lista = 2
lista-de-livres = 0

0
1
1
3
2
23
4
3
-1
4
10
5
5
3
-1
caso 3: Neste caso queremos remover um elemento que não é o primeiro da lista.
Suponha que queiramos remover o elemento 10 da lista dada acima. A lista deve ser
percorrida a partir de inicio-da-lista até encontrar o elemento a ser removido ou até chegar
ao final da lista. Como o elemento 10 pertence a lista a processo pára indicando que o
elemento que se deseja remover está na posição 4 do vetor. Mas para realizar a remoção é
preciso saber qual é o nó cujo elemento antecede o elemento 10. Neste caso, é o elemento
23 que está no nó 2. Agora é possível realiza a remoção.
inicio-da-lista = 2
lista-de-livres = 4
0
1
1
3
2
23
5
3
4
-1
0
5
3
-1
Algoritmo
inteiro Remove_Elem ( endereço da lista, elemento a ser removido)
inicio
se lista está vazia
então a função retorna o valor -1;
se elemento a ser removido está no inicio da lista
então inicio
atribui à variável auxiliar pos o valor de inicio-da-lista;
atribui à variável inicio-da-lista o conteúdo do campo de ponteiros do nó
pos;
atribui ao o conteúdo do campo de ponteiros do nó pos o
valor de lista-de-livres;
atribui à variável lista-de-livres o endereço de pos;
fim;
senão inicio
atribui à variável anterior o conteúdo de inicio-da-lista;
enquanto não chegou ao fim a lista E elemento não está no nó que sucede
anterior
faça atualiza anterior com o próximo elemento da lista;
se chegou ao final da lista
então a função retorna o valor -1
senão inicio // anterior aponta para o nó que antecede o nó cujo elemento
// queremos remover
atribui à pos a posição do nó que sucede o nó anterior;
atribui ao conteúdo do campo de ponteiros do nó anterior
o conteúdo do campo de ponteiros de pos;
atribui ao conteúdo do campo de ponteiros de pos o conteúdo de
lista-de-livres;
atribui à lista-de-livres o endereço de pos;
fim;
fim;
fim;
5.2 Implementação do TDA lista_ordenada
O estudo e os algoritmos para implementar o TDA para listas ordenadas com alocação de
memória e acesso encadeado forma deixados com exercícios para o leitor.
Download