Академический Документы
Профессиональный Документы
Культура Документы
Listas
SUMRIO
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. Definio Ponteiros Alocao de memria Implementao Busca seqencial Memria livre Criao de lista Destruio de lista Insero e remoo Problemas com ponteiros Pilhas e Filas Listas circulares Listas duplamente encadeadas Concluses
1. Definio
Uma lista um arranjo seqencial de elementos. Dada uma lista L, as seguintes operaes so tpicas Encontrar o primeiro elemento de L Dado um elemento de L, encontrar o prximo ou o anterior Encontrar o k-simo elemento da lista Arrays so listas onde os elementos so de mesmo tamanho e armazenados contiguamente na memria do computador Vamos agora considerar listas encadeadas. Estas no tm as principais restries dos arrays: possvel inserir ou remover elementos em O(1) O problema de overflow no existe, ou melhor, acontece apenas quando a memria do computador se esgota Listas encadeadas tambm tm desvantagens: Utilizam mais memria que arrays (par elemento/elo) Acesso direto - i.e., O(1) - ao k-simo elemento no possvel
2. Ponteiros
Listas (encadeadas) so usualmente implementadas com variveis ponteiros. Uma (varivel) ponteiro contm um endereo de memria. Esse endereo a posio de uma outra varivel na memria. Diz-se que o ponteiro aponta para essa varivel. Por exemplo, se uma varivel x na posio 1004 apontada por uma varivel y na posio 1000, ento a posio 1000 contm o valor 1004 e a varivel y (da posio 1000) um ponteiro para a varivel x (da posio 1004). Por exemplo, na linguagem C, tem-se os seguintes conceitos bsicos para uso de uma varivel ponteiro: int *p; declara uma varivel ponteiro p para inteiros p = # coloca o endereo da varivel num em p q = *p; coloca o valor da varivel apontada por p em q
2. Ponteiros
Exemplo em C
#include <stdio.h> int main(void) { int num, q; int *p; /* declara ponteiro p para inteiros */
num = 100; /* num recebe o valor 100 */ p = # /* p recebe o endereco de num */ q = *p; /* q recebe o valor de num indiretamente por meio de p */ printf("%d \n", q); system("pause"); return 0; } /* imprime 100 */
3. Alocao de memria
Um assunto muito intimamente ligado a estruturas encadeadas a alocao de memria. Esta consiste no processo de solicitar/utilizar memria para o processo de execuo de um programa de computador. A alocao de memria pode ser dividida em dois grupos principais: 1) Alocao Esttica: os dados tm um tamanho fixo e esto organizados seqencialmente na memria do computador. Um exemplo tpico de alocao esttica so os arrays; 2) Alocao Dinmica (alocao encadeada): os dados no precisam ter um tamanho fixo, pois podemos definir para cada dado quanto de memria que desejamos usar. Sendo assim vamos alocar espaos de memria (blocos) que no precisam estar necessariamente organizados de maneira seqencial, podendo estar distribudos de forma esparsa na memria do computador. Um exemplo tpico de alocao encadeada so as listas encadeadas; Na alocao dinmica, vamos pedir para alocar/desalocar blocos de memria, de acordo com a nossa necessidade, reservando ou liberando blocos de memria durante a execuo de um programa. Para poder achar os blocos esparsos na memria usamos as variveis do tipo Ponteiro.
4. Implementao
Elementos so armazenados na memria em endereos arbitrrios Ordem seqencial entre os elementos armazenada explicitamente (elos, ponteiros, links) Deve ser possvel determinar o elo correspondente a cada elemento (p.ex., armazenamento consecutivo usando 2 elos) A lista propriamente s pode ser acessada sabendo-se o endereo do seu primeiro elemento Deve haver alguma maneira de determinar o comprimento da lista (p.ex., elo nulo, comprimento armazenado)
4. Implementao
Vamos assumir: Cada n (par elemento/elo) armazenado em posies contguas de memria Usamos um elo nulo para indicar o fim da lista Uma lista referida por um elo que leva ao primeiro n da lista Sendo assim, vamos propositalmente confundir o conceito de elo e lista.
5. Busca Seqencial
Vamos usar a seguinte notao: Nulo : elo (lista) nulo L: denota o elo que leva ao primeiro n da lista (ou a prpria lista) L^.Elo: denota o elo do primeiro n da lista, ou seja, indica o prximo n da lista. L^.Elemento: denota o elemento armazenado no primeiro n da lista
proc Busca (Lista L, Valor v) /* verso recursiva */ { se L = Nulo ento retornar falso seno se L^.Elemento = v ento retornar verdadeiro seno retornar Busca (L^.Elo, v) }
5. Busca Seqencial
Vamos usar a seguinte notao: tmp: denota um iterador de lista. Isso quer dizer que ele recebe o elo da lista (ou a prpria lista) . Ele serve para percorrer a lista.
proc Busca (Lista L, Valor v) /* verso no recursiva */ { tmp L enquanto tmp Nulo fazer { se tmp^.Elemento = v ento retornar verdadeiro seno tmp tmp^.Elo } retornar falso }
6. Memria Livre
preciso haver algum mecanismo que permita gerenciar a memria livre Quando se quer alocar um n, requisita-se uma rea contgua de memria livre suficientemente grande Aloca(Tipo) retorna um elo para uma rea de memria grande suficiente para guardar uma estrutura de dados do tipo Tipo Ex.: Aloca(NoLista) retorna um elo para um n de lista, isto , uma Lista Quando uma rea de memria no est mais em uso, ela retornada ao gerenciador para ser reutilizada posteriormente Libera(Elo) retorna (devolve, libera) a rea de memria contgua apontada por Elo
6. Memria Livre
Em linguagem C, voc pode alocar e liberar memria usando as rotinas da biblioteca padro malloc( ), que aloca memria e retorna um ponteiro void* para o incio dela, e free( ) que retorna (libera) a memria anteriormente alocada. Ambas as rotinas usam o arquivo de cabealho stdlib.h Exemplo: o fragmento a seguir aloca 1.000 bytes de memria.o ponteiro p (para tipo char) aponta para o incio da memria livre. Em seguida, a memria liberada. char *p; p = malloc(1000); free(p);
Como observao, para a compatibilidade com C++, seria preciso fazer a converso de tipo no fragmento acima, ficando: p = (char *) malloc(1000);
6. Memria Livre
Um outro exemplo: o fragmento a seguir aloca memria para 50 inteiros. O ponteiro p aponta para o incio dessa memria. Em seguida, a memria liberada. int *p; p = malloc(50*sizeof(int)); ou (int *) malloc(50*sizeof(int)); free(p); Se no houver espao livre na memria para atender solicitao, malloc( ) retorna um valor nulo. preciso, preventivamente, testar para saber se a memria foi alocada. O trecho a seguir faz isso. int *p; if ((p =(int *) malloc(100) == NULL) printf(Falta de memria \n)
7. Criao de Lista
Para criar uma lista com um nico elemento igual a v proc CriaListaUnaria (Valor v) { L Aloca (NoLista) L^.Elemento v L^.Elo Nulo retornar L } L v
Para criar uma lista com um elemento igual a v frente de uma lista S S
L v
8. Destruio de lista
Para destruir o primeiro n de uma lista proc DestroiNoLista (var Lista L ) L { tmp L L L^.Elo Libera (tmp) }
DestroiNoLista (L)
tmp L
Obs: Note que na rotina, L um parmetro varivel, isto , passado por referncia.
L tmp
Libera (tmp)
L L^.Elo
L tmp
L tmp ?
8. Destruio de lista
Para destruir uma lista inteira proc DestroiLista (var Lista L) { enquanto L Nulo fazer DestroiNoLista (L) } Obs: Note que na rotina, L um parmetro varivel, isto , passado por referncia.
9. Insero e Remoo
Todos os procedimentos de insero e remoo de elementos de uma lista encadeada podem ser escritos com o auxlio das rotinas CriaNoLista e DestroiNoLista Rotina para inserir um elemento v numa lista ordenada L proc InsereListaOrdenada (Valor v, var Lista L) { se L = Nulo ento L CriaListaUnria (v) seno se L^.Elemento > v ento L CriaNoLista (v, L) seno InsereListaOrdenada (v, L^.Elo) }
9. Insero e Remoo
Rotina para remover um elemento igual a v de uma lista ordenada L
proc RemoveListaOrdenada (Valor v, var Lista L) { se L Nulo ento se L^.Elemento = v ento DestroiNoLista (L) seno RemoveListaOrdenada (v, L^.Elo) }
Enfileira
Incio
Fim Desenfileira
Incio
c c d a b
Fim Incio
a Incio
c Fim
14. Concluses