Listas Lineares

Propaganda
Listas Lineares
Professor Sérgio Furgeri
Listas Lineares
Fundamentos
Uma lista linear é uma coleção L:[a1, a2, ..., an], n ≥ 0, cuja propriedade estrutural baseia-se apenas
na posição relativa dos elementos, que são dispostos linearmente. Se n=0, dizemos que a lista L é
vazia; caso contrário, são válidas as seguintes propriedades:
• a1 é o primeiro elemento de L;
• an é o último elemento de L;
• ak , 1<k<n, é precedido pelo elemento ak-1 e seguido por ak+1 em L.
Diversas operações que podemos realizar sobre listas:
•
•
•
•
•
•
•
•
•
•
•
acessar um elemento qualquer da lista;
inserir um elemento numa posição específica da lista;
remover um elemento de uma posição específica da lista;
combinar duas listas em uma única;
particionar umalista em duas;
obter cópias de uma lista;
determinar o total de elementos na lista;
ordenar os elementos da lista;
procurar um determinado elemento na lista;
apagar uma lista;
outras...
Considerando-se somente as operações de acesso, inserção e remoção, restritas aos extremos da lista,
temos casos especiais que aparecem muito frequentemente na modelagem de problemas a serem
resolvidos por computador. Tais casos especiais recebem também nomes especiais:
• Pilha: lista linear onde todas as inserções, remoções e acessos são realizados em um
único extremo. Listas com esta característica são também denominados listas LIFO
(Last-In / First-Out, ou em português: último que entre / primeiro que sai).
• Fila: lista linear onde todas as inserções são feitas num certo extremo e todas as
remoções e acessos são realizados no outro. Filas são também denominadas listas
FIFO (First-In / First-Out, ou em protuguês, primeiro que entra / primeiro que sai).
• Fila Dupla: lista linear onde as inserções, remoções ou acessos são ralizados em
qualquer extremo. Filas Duplas são também denominadas DEQUE (Double-Ennded
QUEue, ou em português: fila de extremidade dupla). Uma Fila Dupla pode ainda
gerar dois casos especiais: Fila Dupla de Entrada Restrita (se a inserção for restrita a
um único extremo) e Fila Dupla de Saída Restrita (se a remoção for restrita a um
único extremo).
Página 1
Listas Lineares
Professor Sérgio Furgeri
LISTA
PILHA
FILA
FILA DUPLA
FDER
FDSR
É extremamente difícil de se obter uma implementação onde todas as operações sejam com a mesma
eficiência. Por exemplo, uma implementação que facilite o acesso a qualquer elemento da lista,
certamente dificultará a inserção e a remoção de elementos no meio da mesma, como veremos
futuramente.Diante deste problema, estudaremos algumas alternativas de como implementar listas
lineares na memória do computador. Assim, dependendo das operações realizadas com maior
freqüência, podemos fazer escolhas que tornem a nossa aplicação a mais eficiente possível.
Alocação de Memória
Ao desenvolver uma implementaçao para listas lineares, o primeiro problema que surge é: como
podemos armazenar os elementos da lista, dentro do computador?
A alocação de memória, do ponto de vista do programador, esterá em uma das quatro categorias
apresentadas a seguir:
Sequencial
Encadeada
Estática
Estática Sequencial
Estática Encadeada
Dinâmica
Dinâmica Sequencial
Dinâmica Encadeada
Alocação Estática versus Dinâmica
Dizemos que as variáveis de um programa têm alocação estática se a quantidade total de memória
utilizada pelos dados é previamente conhecida e definida de modo imutável, no próprio código-fonte
do programa. Durante toda a execução, a quantidade de memória utilizada pelo programa não varia.
Por outro lado, se o programa é capaz de criar novas variáveis enquanto executa, isto é, se áreas de
memória que não foram declaradas no programa passam a existir durante a sua execução, então
dizemos que a alocação é dinâmica. Os atributos seqüencial e encadeada só fazem sentido se a
memória considerada for armazenar uma coleção de objetos.
Alocação Sequencial
A forma mais natural de armazenar uma lista dentro do computador consiste em colocar os seus
elementos em células de memória consecutivas, um após o outro. Assim, se cada célula tem um
endereço único ε e utiliza k bytes, temos:
Página 2
Listas Lineares
...
Professor Sérgio Furgeri
ε–k
ε
ε+k
ai-1
ai
ai+1
k
•
•
•
Endereço (ai ) = ε
Endereço (ai-1 ) = ε - k
Endereço (ai+1) = ε + k
De forma genérica, assumindo que o elemento a1 encontra-se na célula de endereço B, temos a
equação: ai = B+(i-1)k.
...
B+0k B+1k b+2k
a1
a2
a3
...
B+(i-1)k
...
ai
|--k--|
B+(i-1)k
an
...
A maior vantagem no uso de uma área seqüencial de memória para armazenar uma lista linear é que,
dado o endereço inicial de cada área alocada e o índice i de um elemento qualquer da lista, podemos
acessá-lo imediatamente. O ponto fraco desta forma de armazenamento aparece quando precisamos
inserir ou suprimir elementos do meio da lista.
Cada elemento de uma lista linear é chamado de NÓ.
Exemplo de uma lista Linear Seqüencial em Pascal:
Criar uma lista em Pascal que armazene os seguintes dados sobre 4 pessoas: Código de identificação,
nome, naturalidade, estado e Nascimento.
O programa deve permitir a digitação dos dados das 4 pessoas e a seguir possibilitar a busca dos
dados de uma das pessoas através de seu código de identificação.
program pessoas;
uses crt;
type
Tdados_pessoais=record {armazena a tabela com os dados pessoais}
pessoaid:integer;
nome:string;
naturalidade:string;
uf:string[2];
nasc:string[10];
end;
var
iProcura, iNoh:integer;
Página 3
Listas Lineares
Professor Sérgio Furgeri
dados_pessoais:array[1..4] of Tdados_pessoais;
i:integer;
const
count=4;
function busca(ipessoaid:integer):integer;
var
i:integer;
begin
for i:=1 to count do
if dados_pessoais[i].pessoaid=ipessoaid then
begin
busca:=i;
exit;
end;
end;
begin
clrscr;
{Le a tabela}
for i:=1 to count do
begin
Writeln('Digite os dados da pessoa ',i);
Writeln;
write('Codigo......... :');
readln(dados_pessoais[i].pessoaid);
write('Nome........... :');
readln(dados_pessoais[i].nome);
write('Naturalidade... :'); readln(dados_pessoais[i].naturalidade);
write('UF............. :');
readln(dados_pessoais[i].uf);
write('Nascimento..... :'); readln(dados_pessoais[i].nasc);
clrscr;
end;
writeln('Digite a chave procurada');
readln(iprocura);
iNoh:=busca(iprocura);
writeln('A chave eh: ', iNoh);
writeln('Identificacao...:', dados_pessoais[iNoh].pessoaid);
writeln('Nome............:', dados_pessoais[iNoh].nome);
writeln('Naturalidade....:', dados_pessoais[iNoh].naturalidade);
writeln('Estado..........:', dados_pessoais[iNoh].uf);
writeln('Nascimento......:', dados_pessoais[iNoh].nasc);
readkey;
end.
Como fazer para mostrar todas as pessoas cadastradas?
Como fazer para remover a 2 pessoa da lista?
Página 4
Listas Lineares
Professor Sérgio Furgeri
Alocação Encadeada
Ao invés de manter os elementos agrupados numa área contínua de memória, isto é, ocupando células
consecutivas, na alocação encadeada os elementos podem ocupar quaisquer células (não
necessariamente consecutivas) e, para manter a relação de ordem linear, juntamente com cada
elemento é armazenado o endereço do próximo elemento da lista.
Desta forma, na alocação encadeada, os elementos são armazenados em blocos de memória
denominados nodos, sendo que cada nodo é composto por dosi campos: um para armazenar dados e
outro para armazenar endereço.
Dois endereços especiais devem ser destacados:
• O enerço do primeiro elemento da lista (L);
• O endereço do elemento fictício que segue o último elemento da lista (Φ).
Endereço
Conteúdo
L= 3FFA
a1
1C34
Primeiro elemento, acessível a partir de L .
1C34
a2
BD2F
Note que o segundo elemento não ocupa a um
endereço consecutivo àquele ocupado por a1 .
...
BD2F
...
a3
AC12
1000
ai
3A7B
Cada nodo armazena um elemento e o
endereço do próximo elemento da lista.
5670
an-2
14F6
14F6
an-1
5D4A
5D4A
an
Φ
Último elemento da cadeia, o endereço nulo Φ indica
que o elemento an não tem um sucessor
A alocação encadeada apresenta com maior vantagem a facilidade de inserir ou remover elementos do
meio da lista. Como os elementos não precisam estar armazenados em posições consecutivas de
memória, nenhum dado precisa ser movimentado, bastando atualizar o campo de ligação do elemento
que precede aquele inserido ou removido. Por exemplo, para remover o elemento a2 da lista
representada no esquema acima, basta mudar o nodo no endereço 3FFA de (a1, 1C34) para (a1,
BD2F). Como apenas o primeiro elemento é acessível diretamente através do endereço L, a grande
desvantagem da alocação encadeada surge quando desejamos acessar uma posição específica dentro
da lista. Neste caso, devemos partir do primeiro elemento e ir seguindo os campos de ligação, um a
um, até atingir a posição desejada. Obviamente, para listas externas, esta operação pode ter um alto
custo em relação a tempo.
Página 5
Listas Lineares
Professor Sérgio Furgeri
Exercícios com listas lineares
1. Uma aplicação precisava de uma estrutura de dados para representar com eficiência um estante de
livros, dentro do computador, para efeito de algumas simulações. O programador resolveu representar
a estante por uma lista linear E:[P1, P2, ..., Pn], onde cada elemento Pi é uma prateleira, também
representada por uma lista Pi :[L1, L2, ..., L m], cujos elementos Lj são livros. Considerando as
características físicas dos objetos, que categoria de alocação você escolheria para representar cada
uma das listas? Justifique suas escolhas.
R: Segundo o enunciado, a estante de livros E é representada por uma lista linear [P1, P2, ..., Pn], onde
cada Pi é uma prateleira representada por outra lista [L1, L2, ..., L m], tal que cada Lj é um livro
qualquer. Admita que o número de prateleiras numa estante é fixo, e que o número de livros é
variável. Assim, seria adequado implementar a lista E usando alocação estática seqüencial, pois
podemos prever o total de prateleiras em cada estante no momento em que escrevemos o programa
simulador. Já as listas Pi deveriam ser implementadas usando-se alocação dinâmica encadeada, pois
além de não sabermos de antemão qual a quantidade exata de livros em cada prateleira, eles estarão
constantemente sendo retirados e recolocados nas estantes, o que caracteriza uma coleção com
ordenação altamente dinâmica.
Este exercício mostra a relevância dos aspectos físicos dos objetos, cujas abstrações pretendemos
manipular num programa, na hora em que temos que decidir qual categoria de alocação
empregaremos para representá-los!
2. Por que motivo as listas devem ser implementadas na forma seqüencial, quando acessar um
elemento arbitrário for uma operação muito requisitada?
Porque basta indicar seu endereço, uma vez que não é necessário ler toda a lista.
3. Por que motivo os valores L e Φ são considerados especiais no esquema de alocação encadeada ?
Porque o L contem o endereço do primeiro elemento da lista e o Φ o último.
4. Considere as variáveis representadas a seguir, onde L é um inteiro, D é um vetor de caracteres e i é
um valor de inteiros:
L:
?
D:
h
c
a
f
e
g
d b
I:
?
?
?
?
?
?
?
?
Sabendo-se que as variáveis acima representam, de forma encadeada e estática, a lista linear L:[a, b,
c, d, e, f, g, h]:
a) Qual o valor que deve estar armazenado na variável L? (3)
b) Quais os valores armazenados no vetor I? (8, 2, 7, 5, 4, 6, 1, 0)
c) Quais as instruções necessárias para remover o elemento c da lista?
d) Como inserir outro elemento b no lugar do c que foi removido?
e) Se um elemento está na posição p, como encontrar seu predecessor? Basta ler o índice de I-1
f) Codifique uma rotina em pascal para imprimir os elementos da lista L em ordem e resolver
todas as questões acima.
Página 6
Listas Lineares
Professor Sérgio Furgeri
Implementação em pascal do exercício 4.
program lista1;
uses crt;
var
primElemento, i:Integer;
L:array [1..8] of char;
Li:array [1..8] of integer;
procedure mostraLista;
begin
Writeln(L[primElemento]);
for i:=1 to 8 do
begin
if Li[i]=0 then break;
Writeln(L[Li[i]]);
end;
end;
begin
clrscr;
primElemento:=3;
L[1]:='h'; L[2]:='c'; L[3]:='a'; L[4]:='f';
{ mostra os elementos da lista L}
for i:=1 to 8 do
Writeln(L[i]);
L[5]:='e';
{ valores iniciais necessários para o vetor Li }
Li[1]:=8; Li[2]:=2; Li[3]:=7; Li[4]:=5; Li[5]:=4;
mostraLista;
readkey;
clrscr;
L[6]:='g';
L[7]:='d';
L[8]:='b';
Li[6]:=6;
Li[7]:=1;
Li[8]:=0;
{ solução da questão C: para remover o elemento 'c' da lista ‚ necessário mover os índices }
for i:=2 to 7 do
Li[i]:=Li[i+1];
mostraLista;
readkey;
clrscr;
{ solução da questão D }
for i:=8 downto 3 do
Li[i]:=Li[i-1];
Li[2]:=8;
mostraLista;
readkey;
end.
Página 7
Listas Lineares
Professor Sérgio Furgeri
Exercícios referentes a listas encadeadas.
Fazer um programa em pascal para classificar os vetores seguintes através da utilização de um vetor
auxiliar.
a) Lista de nomes de pessoas.
Paulo
Tiago
João
Lucas
Maria
Pedro
André
Jonas
b) Lista de valores inteiros
4587
1254
5687
2542
3658
9574
5826
5479
c) Lista de estados do Brasil
SP
RJ
SC
AM
PE
DF
TO
PR
Simulação do uso de listas encadeadas na criação de arquivos de índice.
O arquivo seguinte usa três vetores para simular a criação de arquivos de índices usados em tabelas de
dados.
program lista2;
uses crt;
{ esse programa simula a criação de um arquivo de índice }
var
i,a,b:Integer;
L:array [1..10] of string;
C:array [1..10] of string;
V:array [1..10] of integer;
nomeMenor:String;
indiceMenor:Integer;
begin
clrscr;
{ Entrada dos elementos da lista - os nomes podem ser variáveis }
L[1]:='Helena';
L[2]:='Jimena';
L[3]:='Fabio';
L[4]:='Ana';
L[5]:='Elaine';
L[6]:='Bruno';
L[7]:='Sandra';
L[8]:='Paulo';
L[9]:='Monica';
L[10]:='Klauss';
{ ------------------------------------------------------------- }
for i:=1 to 10 do
C[i]:=L[i];
{ copia o vetor em um auxiliar }
for a:=1 to 10 do
begin
Página 8
Listas Lineares
Professor Sérgio Furgeri
nomeMenor:='ZZ';
for b:=1 to 10 do
begin
if (nomeMenor > C[b]) and (C[b]<>'*') then
begin
nomeMenor := C[b];
indiceMenor:=b;
end;
end;
V[a]:=indiceMenor;
C[indiceMenor]:='*';
{ trecho apenas ilustrativo, passo a passo a busca dos nomes }
clrscr;
for i:=1 to 10 do
writeln(i,' ',C[i]);
readkey;
{ ---------------------------------------------------------- }
end;
{ mostra a lista L ordenada através do vetor V }
for i:=1 to 10 do
writeln(L[V[i]]);
{ -------------------------------------------- }
readkey;
end.
Exercício:
Crie um programa em pascal que receba uma lista de dados sobre 5 produtos. Cada produto deve
conter código, nome, qtde em estoque e preço unitário. Depois de receber os dados referentes ao
produto, o programa deve mostrar um menu na tela de forma a permitir ao usuário a classificação dos
produtos de acordo com as opções apresentadas a seguir:
1 – classificar por código
2 – classificar por nome
3 – classificar por quantidade em estoque
4 – classificar por preço unitário.
Esses itens referem-se à simulação de 4 arquivos de índice para os produtos.
Página 9
Download