Escolar Documentos
Profissional Documentos
Cultura Documentos
APOSTILA
LISTAS LINEARES
INTRODUÇÃO
LISTAS LINEARES
A lista linear é a mais simples estrutura de dados que existe na maioria das
linguagens de programação. É conhecida mais comumente como vetor ou array
(em inglês), e é implementada na memória estática.
A = (a1,...,an), n 0.
caixa_ocupado[5] verdadeiro;
var i : int;
i 1;
enquanto caixa_ocupado[i] falso faça
i i+1;
fim enquanto;
Posiçã 1 2 3 4 5 6 7 8
o
Dado A B C D E F G
fim 7;
para i de fim até 3 faça
dado[i+1] dado[i];
fim para;
fim fim +1;
Posiçã 1 2 3 4 5 6 7 8
o
Dado A B C C D E F G
dado[3] „M‟;
Logo, teremos:
Posiçã 1 2 3 4 5 6 7 8
o
Dado A B M C D E F G
Nota-se também, que quanto maior a lista e quanto menor for o valor da posição
em que desejamos fazer a inserção, mais tempo será necessário para o
processamento. Este problema pode ser solucionado se colocarmos o início
como sendo uma variável. Assim, podemos deslocar tanto os elementos da
esquerda como os da direita. Este procedimento está esquematizado abaixo:
Pos. 1 2 3 4 5 6 7 8 9 10 11
Dad A B C D E F G
o
início 3;
fim 9;
Posiçã 1 2 3 4 5 6 7 8
o
Dado A B M C D E F G
O procedimento é:
fim 8;
para i de 6 até fim faça
dado[i-1] dado[i];
fim para;
fim fim - 1;
A lista ficará:
Posiçã 1 2 3 4 5 6 7 8
o
Dado A B M C E F G G
Podemos observar que a posição 8 ficará “marcada” com o dado G, porém nós
remarcamos o final da lista de 8 para 7.
LISTAS ENCADEADAS
O DESCRITOR
O nó descritor de uma lista pode conter outras informações sobre a lista como a
quantidade de nós na lista (como nos modelos apresentados neste trabalho),
descrição dos dados contidos nos nós, etc.
Uma lista encadeada simples é aquela que em cada nó possui apenas uma
referência. Esta referência serve para indicar seu nó sucessor.
LISTAS DUPLAMENTE ENCADEADAS
(p^.predecessor)^.sucessor = (p^.sucessor)^.predecessor = p
OS OPERADORES DE LISTAS
A definição completa de uma estrutura de dados inclui tanto sua forma estrutural
como a disciplina de acesso, o que define sua coleção de operadores válidos.
* A escolha da linguagem Pascal foi feita pelo motivo de ser uma linguagem
simples, que possui a manipulação de variáveis tipo ponteiro e também por ser
conhecida amplamente. Esses modelos (Modelo1.pas e Modelo2.pas) estão
em linguagem Pascal no disquete do trabalho e mais dois exemplos de
aplicações de listas (Exemplo1.pas - arranjar em ordem alfabética um grupo de
palavras; e Exemplo2.pas - um pequeno exemplo de manipulação de banco de
dados).
PROGRAM modelo_lista_linear_simples;
no = RECORD
proximo : pont;
{Como a lista é simplesmente encadeada, só poderá haver ponteiro em uma
direção}
END;
nos : INTEGER;
inicio, fim : pont;
{Definição do registro do descritor, onde nos é a quantidade de nós da lista;
inicio e fim, respectivamente são os ponteiros para início e fim da lista}
END;
BEGIN
descritor.nos:=0;
{Como a lista está vazia o número de nós deverá ser 0(zero)}
descritor.inicio:=NIL;
descritor.fim:=NIL;
{Se a lista está vazia, obviamente o início e fim da lista não existem}
END;
PROCEDURE insere_direita;
{Inserir a direita significa, inserir o nó na última posição da lista}
VAR p : pont;
{Declara p como um ponteiro para o novo nó da lista}
BEGIN
NEW(p);
{Aloca memória para o nó apontado por p}
p^.proximo:=NIL;
{Como o novo nó está sendo inserido na última posição da lista, não existe
nenhum nó a sua frente}
ELSE
(descritor.fim)^.proximo:=p;
{Senão, esta linha faz com que o nó próximo ao último nó da lista aponte para o
novo}
descritor.fim:=p;
{Já esta linha define que o novo nó inserido é o último da lista}
INC(descritor.nos);
{Aumenta o número de nós existentes no descritor em 1}
END;
PROCEDURE insere_esquerda;
{Inserir a esquerda significa, inserir o nó na primeira posição da lista}
VAR p : pont;
{Declara p como um ponteiro para o novo nó da lista}
BEGIN
NEW(p);
{Aloca memória para o nó apontado por p}
p^.proximo:=descritor.inicio;
{Faz com que o nó seguinte ao novo nó (apontado por p) aponte para o antigo
primeiro nó da lista}
descritor.inicio:=p;
{Define o novo nó como o primeiro da lista}
INC(descritor.nos);
{Aumenta o número de nós existentes no descritor em 1}
END;
BEGIN
NEW(p);
{Aloca memória para o nó apontado por p}
EXIT;
{Sai da PROCEDURE }
END;
EXIT;
{Sai da PROCEDURE}
END;
q:=descritor.inicio;
{Faz com que o ponteiro q aponte para o primeiro nó da lista}
q^.proximo:=p;
{O nó seguinte ao nó apontado pelo ponteiro q aponta para o novo nó (apontado
por p)}
INC(descritor.nos);
{Aumenta o número de nós existentes no descritor em 1}
END;
PROCEDURE remove_direita;
{Remover a direita significa remover o último nó da lista}
i : INTEGER;
{Índice para a instrução FOR}
BEGIN
CASE descritor.nos OF
0 : {Rotina de erro};
{Se não existirem nós na lista, não será possível a remoção, daí chama-se uma
rotina de manipulação do erro}
1 : BEGIN
{Se existir apenas um nó na lista então:}
p:=descritor.inicio;
{O ponteiro p aponta para o primeiro nó da lista}
inicializa;
{Já que a lista ficará vazia podemos fazer o mesmo procedimento de inicializar o
descritor}
DISPOSE(p);
{Desaloca a memória criada do nó apontado por p}
EXIT;
{Sai do PROCEDURE}
END;
END;
p^.proximo:=descritor.inicio;
{O proximo do ponteiro p aponta para o primeiro nó da lista}
q:=p^.proximo;
{Agora q aponta para o nó seguinte em relação a p, ou seja, aponta para o nó
que vai ser removido}
p^.proximo:=NIL;
{Como a lista é linear o ponteiro p(o último) aponta para NIL}
descritor.fim:=p;
{Indica que o nó apontado por p será o último da lista}
DISPOSE(q);
{Desaloca a memória criada de nó apontado por q}
DEC(descritor.nos);
{Diminui a variável do descritor de quantidade de nós em uma unidade}
END;
PROCEDURE remove_esquerda;
{Remover a esquerda significa remover o primeiro nó da lista}
VAR p : pont;
{Declara p como ponteiro para o nó que vai ser removido}
BEGIN
CASE descritor.nos OF
0 : {Rotina de erro};
{Se não existirem nós na lista, não será possível a remoção, daí chama-se uma
rotina de manipulação do erro}
1 : BEGIN
{Se existir apenas um nó na lista então:}
p:=descritor.inicio;
{O ponteiro o aponta para o primeiro nó da lista}
inicializa;
{Já que a lista está vazia podemos fazer o mesmo procedimento de inicializar o
descritor}
DISPOSE(p);
{Desaloca a memória criada do nó apontado por p}
EXIT;
{Sai do PROCEDURE}
END;
END;
p:=descritor.inicio;
{O ponteiro p aponta para o primeiro nó da lista, este será removido}
descritor.inicio:=p^.proximo;
{O primeiro nó da lista será o nó seguinte a p}
p^.proximo:=NIL;
{Por questões de segurança fazemos com que o nó seguinte a p aponte para
NIL}
DISPOSE(p);
{Desaloca a memória criada para armazenar o primeiro nó}
DEC(descritor.nos);
{Diminui o número de nós da lista em 1}
END;
PROCEDURE remove_posicao(n : INTEGER);
{Remover uma posição n qualquer significa remover um nó em uma posição
intermediária da lista}
i : INTEGER;
{Índice para ser utilizado na instrução FOR}
BEGIN
EXIT;
{Sai do PROCEDURE}
END;
EXIT;
{Sai do PROCEDURE}
END;
p^.proximo:=descritor.inicio;
{Nesta linha o próximo do ponteiro p aponta para o primeiro nó da lista}
q:=p^.proximo;
{O ponteiro q aponta para o nó que vai ser removido}
p^.proximo:=q^.proximo;
{O nó seguinte ao ponteiro p aponta para o nó seguinte do nó seguinte
apontado por q}
q^.proximo:=NIL;
{Por questões de segurança fazemos q apontar para NIL}
DISPOSE(q);
{Desaloca a memória criada do nó apontado por q}
DEC(descritor.nos);
{Diminui o número de nós da lista em 1}
END;
VAR p : pont;
{Declaração do ponteiro que irá percorrer a lista}
BEGIN
p^.proximo:=descritor.inicio;
{O próximo do ponteiro p aponta para o primeiro nó da lista}
END;
PROCEDURE modifica(n : INTEGER);
{Rotina para a modificação dos dados armazenados no nó da posição n}
VAR p : pont;
{Declaração do ponteiro que irá percorrer a lista}
BEGIN
END;
PROGRAM modelo_lista_linear_duplamente_encadeada;
no = RECORD
END;
END;
PROCEDURE inicializa;
{Esta PROCEDURE serve para inicializar o descritor da lista}
BEGIN
descritor.nos:=0;
{Como a lista está vazia o número de nós deverá ser 0(zero)}
descritor.inicio:=NIL;
descritor.fim:=NIL;
{Se a lista está vazia obviamente o início e o fim da lista não existem}
END;
PROCEDURE insere_direita;
{Inserir a direita significa inserir o nó na última posição da lista}
VAR p : pont;
{Declara p como um ponteiro para o novo nó da lista}
BEGIN
NEW(p);
{Aloca memória para o nó apontado por p}
p^.proximo:=NIL;
{Como a lista é linear , o último nó da lista tem que apontar para NIL}
p^.anterior:=descritor.fim;
{Como o novo nó será o último ele deverá ser precedido do último nó antigo}
IF descritor.nos<>0 THEN BEGIN
(descritor.fim)^.proximo:=p;
{Se a lista não estiver vazia então o nó seguinte ao último nó antigo deverá
apontar para o novo}
END;
descritor.fim:=p;
{Esta linha define que o novo nó inserido estará na última posição da lista}
INC(descritor.nos);
{Aumenta o número de nós existentes em 1}
END;
PROCEDURE insere_esquerda;
{Inserir a esquerda significa, inserir o nó na primeira posição da lista}
VAR p : pont;
{Declara p como um ponteiro para o novo nó da lista}
BEGIN
NEW(p);
{Aloca memória para o nó apontado por p}
p^.proximo:=descritor.inicio;
{Faz com que o nó seguinte ao novo nó (apontado por p aponte para o antigo
primeiro nó da lista}
p^.anterior:=NIL;
{Como o nó está sendo inserido na direita, ele não estará sendo precedido por
nenhum outro nó}
IF descritor.nos<>0 THEN
(descritor.inicio)^.anterior:=p
{Se a lista não estiver vazia o nó anterior ao antigo primeiro será o novo}
ELSE
descritor.fim:=p;
{Senão, como a lista está vazia o novo nó também será o último da lista}
descritor.inicio:=p;
{Define o novo nó como o primeiro da lista}
INC(descritor.nos);
{Aumenta o número de nós existentes em 1}
END;
BEGIN
NEW(p);
{Aloca memória para o nó apontado por p}
EXIT;
{Sai da PROCEDURE }
END;
EXIT;
{Sai da PROCEDURE }
END;
q^.proximo:=descritor.inicio;
{Faz com que o próximo do ponteiro q aponte para o primeiro nó da lista}
p^.proximo:=q^.proximo;
{O nó seguinte ao novo nó(p) aponta para onde o nó seguinte do anterior(q)
aponta}
p^.anterior:=q;
{O nó anterior ao nó apontado por p aponta para q}
q^.proximo:=p;
{O nó seguinte ao nó apontado pelo ponteiro q aponta para o novo nó(apontado
por p)}
(p^.proximo)^.anterior:=p;
{Para fechar a cadeia, o nó seguinte ao novo deverá estar conectado com o
novo nó}
END;
PROCEDURE remove_direita;
{Remover a direita significa remover o último nó da lista}
VAR p,q : pont;
{Declara p e q como ponteiros para nó. Onde q apontará para o nó que irá ser
removido; e p percorrerá a lista}
BEGIN
CASE descritor.nos OF
0 : {Rotina de erro};
{Se não existirem nós na lista, não será possível a remoção, daí chama-se a
rotina de manipulação do erro}
1 : BEGIN
{Se existir apenas um nó da lista então:}
p:=descritor.inicio;
{O ponteiro aponta para o primeiro nó da lista}
inicializa;
{Já que a lista ficará vazia, podemos fazer o mesmo procedimento de inicializar
o descritor}
DISPOSE(q);
{Desaloca a memória criada do nó apontado por p}
EXIT
{Sai da PROCEDURE}
END;
END;
p:=(descritor.fim)^.anterior;
{O ponteiro p aponta para o penúltimo nó da lista}
p^.proximo:=NIL;
{Como a lista é linear o ponteiro p(o último) aponta para NIL}
(descritor.fim)^.anterior:=NIL;
{Como agora o penúltimo nó será o último, não existe nenhum outro nó
seguinte, daí porque proximo aponta para NIL}
q:=descritor.fim;
{Faz com que q aponte para o nó a ser removido, ou seja, o último da lista}
DISPOSE(q);
{Desaloca a memória criada do nó apontado por q}
descritor.fim:=p;
{Indica que o nó apontado por p será o último da lista}
DEC(descritor.nos);
{Diminui o número de nós da lista em 1 }
END;
PROCEDURE remove_esquerda;
{Remover a esquerda significa remover o primeiro nó da lista}
VAR p : pont;
{Declara p que será o nó removido}
BEGIN
CASE descritor.nos OF
0 : {Rotina de erro};
{Se não existirem nós na lista, não será possível a remoção, daí chama-se uma
rotina de manipulação do erro}
1 : BEGIN
{Se existir apenas um nó na lista então:}
p:=descritor.inicio;
{O ponteiro p aponta para o primeiro nó da lista, este será removido}
p^.anterior:=NIL;
p^.proximo:=NIL;
{Por questões de segurança, fazemos com que o nó apontado por p esteja
completamente isolado}
inicializa;
{Já que a lista está vazia podemos fazer o mesmo procedimento de inicializar o
descritor}
DISPOSE(p);
{Desaloca a memória criada do nó apontado por p}
EXIT
{Sai da PROCEDURE}
END;
END;
p:=descritor.inicio;
{O ponteiro p aponta para o primeiro nó da lista}
descritor.inicio:=p^.proximo;
{Agora o segundo nó da lista torna-se o primeiro}
(descritor.inicio)^.anterior:=NIL;
{O nó anterior do primeiro nó de uma lista linear não existe, por isso seu anterior
é nulo}
p^.proximo:=NIL;
{Por segurança aterra-se o ponteiro p}
DISPOSE(p);
{Desaloca a memória criada para armazenar o antigo primeiro nó}
DEC(descritor.nos);
{Diminui o número de nós da lista em 1 }
END;
VAR p: pont;
i : INTEGER;
BEGIN
IF ((n<1) OR (n>descritor.nos)) THEN {Rotina de erro};
{Esta linha prevê um erro na entrada da posição}
EXIT;
{Sai do PROCEDURE}
END;
EXIT;
{Sai do PROCEDURE}
END;
p^.proximo:=descritor.inicio;
{Nesta linha o próximo do ponteiro p aponta para o primeiro nó da lista}
(p^.anterior)^.proximo:=p^.proximo;
{Esta rotina faz com que o nó seguinte ao anterior do apontado por p aponte
para o seguinte de p}
(p^.proximo)^.anterior:=p^.anterior;
{Esta rotina faz com que o nó seguinte ao anterior do apontado por p aponte
para o anterior a p}
p^.proximo:=NIL;
p^.anterior:=NIL;
{Aterramos o nó apontado por p por questões de segurança}
DISPOSE(p);
{Desaloca a memória cria do nó apontado por p}
DEC(descritor.nos);
{Diminui o número de nós da lista em 1}
END;
VAR p : pont;
{Declaração do ponteiro que irá percorrer a lista}
BEGIN
END;
VAR p : pont;
{Declaração do ponteiro que irá percorrer a lista}
BEGIN
END;
PROPRIEDADES
(descritor.fim)^.sucessor = descritor.início;
(descritor.fim)^.sucessor = descritor.início;
(descritor.início)^.predecessor = descritor.início;
PROGRAM modelo_lista_circular_simples;
TYPE pont = ^no;
no = RECORD
{Definição do tipo de dado do nó. Exemplo: nome
STRING[20];}
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);
{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);
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;
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;