Académique Documents
Professionnel Documents
Culture Documents
ecv2001@zipmail.com.br
Aplicaes de Listas
www2.50megs.com/tpascal
LISTAS LINEARES
1- INTRODUO
A lista linear uma forma de representao, como estrutura linear, onde o objetivo
que a representao de dados de um problema no computador seja de tal maneira, que o
algoritmo que os utilize seja auxiliado em sua tarefa de obter uma soluo de forma
confivel e eficiente.
Para a compreenso do funcionamento da lista, necessrio compreendermos o
funcionamento da memria do computador.
A memria do computador um recurso que pode ser acessado de duas formas
por um programa:
Primeiro, um algoritmo pode alocar estruturas de dados no que chamaremos de
memria esttica, alocao esta que deve ser feita antes de sua execuo;
A = (a1,...,an), n 0.
Chamamos de aks de ns, e geralmente impomos a condio de que todos os ns
de uma lista devem pertencer ao mesmo conjunto, por exemplo, todos os a ks devem ser
nmeros inteiros. Os ns podem ser listas tambm, produzindo assim o que conhecemos
por matrizes de duas ou mais dimenses. A lista A pode ser tambm vazia, correspondendo
ao caso especial em que n=0. Ns representamos esse caso especial assim:
A = ( ).
Em virtude da maneira como a maioria das linguagens de programao os
implementa, os ns de uma lista linear so armazenados de forma contgua. Ou seja, na
memria do computador, o primeiro n imediatamente seguido pelo segundo, o segundo
pelo terceiro e assim por diante, at o final da lista. Essa forma de armazenamento
obviamente compacta, mas, mais importante, permite acesso rpido a qualquer elemento,
pois o processo de endereamento extremamente simples: o prprio compilador da
linguagem que utilizamos se encarrega de fornecer o endereo correto. Por exemplo, para
indicarmos que o quinto caixa est ocupado num dado instante da simulao de um banco,
utilizaramos o seguinte segmento de cdigo:
caixa_ocupado[5] verdadeiro;
Similarmente, o segmento de cdigo abaixo encontraria o primeiro caixa
disponvel:
var i : int;
i 1;
enquanto caixa_ocupado[i] falso faa
i i+1;
fim enquanto;
Em nenhum desses dois casos foi necessrio preocuparmo-nos com o acesso aos
ns da lista. O compilador da linguagem se encarregaria de gerar os endereos das clulas
contendo os membros de caixa_ocupado.
Caso desejemos adicionarmos um n a este tipo de lista, deveremos deslocar os
ns de tal forma que possamos encaix-lo entre dois ns j existentes. Supomos que
deseja-se colocar o dado M na posio 3 da lista abaixo:
Posio
Dado
1
A
2
B
3
C
4
D
5
E
6
F
7
G
1
A
2
B
3
C
4
C
5
D
6
E
7
F
8
G
1
A
2
B
3
M
4
C
5
D
6
E
7
F
8
G
Nota-se tambm, que quanto maior a lista e quanto menor for o valor da posio
em que desejamos fazer a insero, mais tempo ser necessrio para o processamento.
Este problema pode ser solucionado se colocarmos o incio como sendo uma varivel.
Assim, podemos deslocar tanto os elementos da esquerda como os da direita. Este
procedimento est esquematizado abaixo:
Pos.
Dad
o
3
A
4
B
5
C
6
D
7
E
8
F
9
G
10
11
incio 3;
fim 9;
Assim, poderamos incluir M entre B e C, deslocando somente A e B para a
esquerda. Para esta, verifica-se tambm a necessidade de comearmos com A, na posio
de 3 para 2, por 2 se tratar de uma posio vazia.
Para excluirmos um n, o procedimento mais fcil, pois basta deslocarmos todos
os ns a sua direita, at o fim, uma posio para a esquerda. Suponhamos que desejemos
retirar a letra D da lista abaixo:
Posio
Dado
1
A
2
B
3
M
4
C
5
D
6
E
7
F
8
G
O procedimento :
fim 8;
para i de 6 at fim faa
dado[i-1] dado[i];
fim para;
fim fim - 1;
A lista ficar:
Posio
1
2
3
4
5
6
7
8
Dado
A
B
M
C
E
F
G
G
Podemos observar que a posio 8 ficar marcada com o dado G, porm ns
remarcamos o final da lista de 8 para 7.
LISTAS ENCADEADAS
A lista encadeada uma generalizao da lista linear que introduz vrias
alteraes:
Os ns da lista no esto necessariamente armazenados seqencialmente;
Dependendo da forma de implementao, pode no haver um tamanho mximo
predefinido da lista;
Uma lista encadeada simples aquela que em cada n possui apenas uma
referncia. Esta referncia serve para indicar seu n sucessor.
LISTAS DUPLAMENTE ENCADEADAS
Uma lista duplamente encadeada aquela que em cada n possui duas referncias.
Estas referncias servem para indicar seu n sucessor e seu predecessor.
Uma lista duplamente encadeada tem a seguinte propriedade:
(p^.predecessor)^.sucessor = (p^.sucessor)^.predecessor = p
OS OPERADORES DE LISTAS
Imaginemos que as operaes abaixo fossem de interesse na utilizao de listas
encadeadas:
Visitar todos os ns da lista;
inserir um novo dado no fim (ou inicio da lista);
remover o primeiro (ou ltimo) n da lista;
buscar um n na lista.
PROGRAM modelo_lista_linear_simples;
TYPE pont = ^no;
no = RECORD
{Definio do tipo de dado do n.
STRING[20];}
Exemplo: nome
proximo : pont;
END;
TYPE tipo_descritor = RECORD
nos : INTEGER;
inicio, fim : pont;
END;
VAR descritor : tipo_descritor;
PROCEDURE inicializa;
BEGIN
descritor.nos:=0;
descritor.inicio:=NIL;
descritor.fim:=NIL;
END;
PROCEDURE insere_direita;
VAR p : pont;
BEGIN
NEW(p);
ELSE
(descritor.fim)^.proximo:=p;
descritor.fim:=p;
INC(descritor.nos);
END;
PROCEDURE insere_esquerda;
VAR p : pont;
BEGIN
NEW(p);
10
descritor.inicio:=p;
INC(descritor.nos);
END;
BEGIN
NEW(p);
11
EXIT;
{Sai da PROCEDURE }
END;
IF n=descritor.nos+1 THEN BEGIN
insere_direita;
EXIT;
{Sai da PROCEDURE}
END;
{Rotina de entrada de dados, exemplo: READLN(p^.nome);}
q:=descritor.inicio;
p^.proximo:=q^.proximo;
q^.proximo:=p;
INC(descritor.nos);
END;
PROCEDURE remove_direita;
12
i : INTEGER;
BEGIN
CASE descritor.nos OF
0 : {Rotina de erro};
1 : BEGIN
p:=descritor.inicio;
inicializa;
DISPOSE(p);
EXIT;
{Desaloca a memria
apontado por p}
criada
do n
{Sai do PROCEDURE}
END;
END;
p^.proximo:=descritor.inicio;
q:=p^.proximo;
p^.proximo:=NIL;
13
descritor.fim:=p;
DISPOSE(q);
DEC(descritor.nos);
{Desaloca a memria
apontado por q}
criada
de
END;
PROCEDURE remove_esquerda;
VAR p : pont;
BEGIN
CASE descritor.nos OF
0 : {Rotina de erro};
1 : BEGIN
p:=descritor.inicio;
inicializa;
DISPOSE(p);
EXIT;
{Desaloca a memria
apontado por p}
criada
do n
{Sai do PROCEDURE}
END;
14
END;
p:=descritor.inicio;
descritor.inicio:=p^.proximo;
p^.proximo:=NIL;
DISPOSE(p);
DEC(descritor.nos);
{Desaloca a memria
armazenar o primeiro n}
criada
para
END;
i : INTEGER;
BEGIN
IF ((n<1) OR (n>descritor.nos)) THEN {Rotina de erro};
15
EXIT;
{Sai do PROCEDURE}
END;
IF n=descritor.nos THEN BEGIN
remove_direita;
EXIT;
{Sai do PROCEDURE}
END;
p^.proximo:=descritor.inicio;
q:=p^.proximo;
p^.proximo:=q^.proximo;
q^.proximo:=NIL;
DISPOSE(q);
DEC(descritor.nos);
{Desaloca a memria
apontado por q}
criada
do n
END;
dados
VAR p : pont;
16
BEGIN
IF ((n<1) OR (n>descritor.nos)) THEN {Rotina de erro};
p^.proximo:=descritor.inicio;
VAR p : pont;
BEGIN
IF ((n<1) OR (n>descritor.nos)) THEN {Rotina de erro};
p^.proximo:=descritor.inicio;
17
PROGRAM
modelo_lista_linear_duplamente_encadeada;
TYPE pont = ^no;
no = RECORD
{Definio do tipo de dado do n.
STRING[20];}
Exemplo: nome
END;
TYPE tipo_descritor = RECORD
nos : INTEGER;
inicio, fim : pont;
END;
VAR descritor : tipo_descritor;
PROCEDURE inicializa;
BEGIN
descritor.nos:=0;
descritor.inicio:=NIL;
descritor.fim:=NIL;
18
END;
PROCEDURE insere_direita;
VAR p : pont;
BEGIN
NEW(p);
p^.anterior:=descritor.fim;
END;
descritor.fim:=p;
INC(descritor.nos);
END;
PROCEDURE insere_esquerda;
19
VAR p : pont;
BEGIN
NEW(p);
p^.anterior:=NIL;
IF descritor.nos<>0 THEN
(descritor.inicio)^.anterior:=p
ELSE
descritor.fim:=p;
descritor.inicio:=p;
INC(descritor.nos);
END;
20
BEGIN
NEW(p);
EXIT;
{Sai da PROCEDURE }
END;
IF n=descritor.nos+1 THEN BEGIN
insere_direita;
EXIT;
{Sai da PROCEDURE }
END;
{Rotina de entrada de dados, exemplo: READLN(p^.nome);}
q^.proximo:=descritor.inicio;
p^.proximo:=q^.proximo;
21
p^.anterior:=q;
q^.proximo:=p;
(p^.proximo)^.anterior:=p;
END;
PROCEDURE remove_direita;
BEGIN
CASE descritor.nos OF
0 : {Rotina de erro};
1 : BEGIN
p:=descritor.inicio;
inicializa;
DISPOSE(q);
{Desaloca a memria
apontado por p}
criada
do n
22
EXIT
{Sai da PROCEDURE}
END;
END;
p:=(descritor.fim)^.anterior;
p^.proximo:=NIL;
(descritor.fim)^.anterior:=NIL;
q:=descritor.fim;
DISPOSE(q);
descritor.fim:=p;
DEC(descritor.nos);
{Desaloca a memria
apontado por q}
criada
do n
END;
PROCEDURE remove_esquerda;
VAR p : pont;
BEGIN
CASE descritor.nos OF
0 : {Rotina de erro};
23
1 : BEGIN
p:=descritor.inicio;
p^.anterior:=NIL;
p^.proximo:=NIL;
inicializa;
DISPOSE(p);
EXIT
{Desaloca a memria
apontado por p}
criada
do n
{Sai da PROCEDURE}
END;
END;
p:=descritor.inicio;
descritor.inicio:=p^.proximo;
(descritor.inicio)^.anterior:=NIL;
p^.proximo:=NIL;
DISPOSE(p);
{Desaloca
a memria criada
armazenar o antigo primeiro n}
para
24
DEC(descritor.nos);
END;
EXIT;
{Sai do PROCEDURE}
END;
IF n=descritor.nos THEN BEGIN
remove_direita;
EXIT;
{Sai do PROCEDURE}
END;
p^.proximo:=descritor.inicio;
(p^.anterior)^.proximo:=p^.proximo;
25
(p^.proximo)^.anterior:=p^.anterior;
p^.proximo:=NIL;
p^.anterior:=NIL;
DISPOSE(p);
DEC(descritor.nos);
END;
{Rotina
para a consulta dos dados
armazenados no n da posio n}
VAR p : pont;
BEGIN
IF ((n<1) OR (n>descritor.nos)) THEN {Rotina de erro};
p^.proximo:=descritor.inicio;
26
VAR p : pont;
BEGIN
IF ((n<1) OR (n>descritor.nos)) THEN {Rotina de erro};
p^.proximo:=descritor.inicio;
27
28
29
PROGRAM modelo_lista_circular_simples;
TYPE pont = ^no;
no = RECORD
{Definio do tipo de dado do n.
STRING[20];}
proximo : pont;
END;
TYPE tipo_descritor = RECORD
nos : INTEGER;
inicio, fim : pont;
END;
VAR descritor : tipo_descritor;
Exemplo: nome
PROCEDURE inicializa;
BEGIN
descritor.nos:=0;
descritor.inicio:=NIL;
descritor.fim:=NIL;
END;
PROCEDURE insere_direita;
VAR p : pont;
BEGIN
NEW(p);
{Rotina para entrada de dados, exemplo READLN(p^.nome);}
p^.proximo:=NIL;
IF descritor.nos=0 THEN
descritor.inicio:=p
ELSE
(descritor.fim)^.proximo:=p;
descritor.fim:=p;
p^.proximo:=descritor.inicio;
INC(descritor.nos);
END;
PROCEDURE insere_esquerda;
VAR p : pont;
BEGIN
NEW(p);
{Rotina para entrada de dados, exemplo READLN(p^.nome);}
p^.proximo:=descritor.inicio;
descritor.inicio:=p;
IF descritor.nos=0 THEN descritor.fim:=p;
(descritor.fim)^.proximo:=p;
INC(descritor.nos);
30
END;
PROCEDURE remove_direita;
VAR p,q : pont;
i : INTEGER;
BEGIN
CASE descritor.nos OF
0 : {Rotina de erro};
1 : BEGIN
p:=descritor.inicio;
inicializa;
DISPOSE(p);
EXIT;
END;
END;
p^.proximo:=descritor.inicio;
FOR i:=1 TO descritor.nos-1 DO p:=p^.proximo;
q:=p^.proximo;
p^.proximo:=descritor.inicio;
descritor.fim:=p;
DISPOSE(q);
DEC(descritor.nos);
END;
PROCEDURE remove_esquerda;
VAR p : pont;
31
BEGIN
CASE descritor.nos OF
0 : {Rotina de erro};
1 : BEGIN
p:=descritor.inicio;
inicializa;
DISPOSE(p);
EXIT;
END;
END;
p:=descritor.inicio;
descritor.inicio:=p^.proximo;
(descritor.fim)^.proximo:=descritor.inicio;
p^.proximo:=NIL;
DISPOSE(p);
DEC(descritor.nos);
END;
32
WRITELN(p^.nome);}
END;
33
BIBLIOGRAFIA
Veloso, Paulo;
Estruturas de dados
Editora Campus
34