Upload
danilo-dias
View
217
Download
0
Embed Size (px)
Citation preview
7/25/2019 19 - aulaIP-ListaEncadeada
1/37
Introduo a Programao
Listas Encadeadas
7/25/2019 19 - aulaIP-ListaEncadeada
2/37
Tpicos da Aula
Hoje aprenderemos que existem, alm devetores, estruturas de dados dinmicasque
podem armazenar colees de dados
Estruturas Dinmicas e Vetores
Conceito de listas encadeadasListas Encadeadas x Vetores
Funes de manipulao de listas encadeadas
Variaes de listas encadeadas
2
7/25/2019 19 - aulaIP-ListaEncadeada
3/37
3
Vetores
Declarao de vetor implica na especificao de seutamanho
No se pode aumentar ou diminuir tamanho
Outra alternativa no uso de vetores alocar
dinamicamente o espao necessrio e guardar
endereo inicial do vetor
Porm, depois de determinado o tamanho do vetor,
no podemos liberar posio de memria arbitrria
Possvel desperdcio ou falta de memria!
7/25/2019 19 - aulaIP-ListaEncadeada
4/37
4
Estruturas Dinmicas
Uma estrutura de dado dinmica consiste emuma estrutura que pode aumentar ou diminuir
de tamanho de acordo com a necessidade da
aplicao (do programador)
Evita desperdcio e/ou falta de memria
Programador encarregado de requisitar e
liberar espaos de memria explicitamente
Uso de alocao dinmica
Requer mais esforo por parte doprogramador!
7/25/2019 19 - aulaIP-ListaEncadeada
5/37
5
Listas Encadeadas
Uma lista encadeada uma estrutura dinmica quepode ser utilizada para armazenar um conjunto de
dados
Junto a cada elemento deve-se armazenar o
endereo para o prximo elemento (elementos
encadeados)
Elemento + ponteiro = n da lista
Diferentemente de vetores, elementos geralmente no so
armazenados em espaos contguos de memria
Caso no exista prximo elemento, o ponteiro para oprximo elemento NULL
7/25/2019 19 - aulaIP-ListaEncadeada
6/37
6
Listas Encadeadas
Para cada novo elemento inserido na lista, aloca-seum espao de memria para armazen-lo
Para remover elemento deve-se liberar o endereo
de memria reservado para armazenar o elemento
O acesso aos elementos sempre seqencialNo se pode garantir que os elementos ocuparo um
espao de memria contguo (no se pode localizar
elementos com base em um deslocamento constante)
7/25/2019 19 - aulaIP-ListaEncadeada
7/37
7
Listas Encadeadas x Vetores
Listas Encadeadas+Uso eficiente da memria
- Complexidade de manipulao da estrutura
- Informao deve ser guardada em uma estrutura
que guarda tambm um endereo (requer maismemoria por informao armazenada)
Vetores
+Simplicidade no acesso (manipulao) aos
elementos da estrutura
- Desperdcio ou falta de memria
- Menor Flexibilidade
7/25/2019 19 - aulaIP-ListaEncadeada
8/37
8
Representao de Listas Encadeadas
info1
primeiro
struct lista {int info ; /* info pode ser de qualquer tipo */struct lista* prox;
} ;typedef struct lista Lista ;
p
r
o
x
info2
p
r
o
x
info3
Informaoarmazenadano n da
lista
Armazena oendereo doprximo n
Armazenaendereo
nulo
fim
7/25/2019 19 - aulaIP-ListaEncadeada
9/37
9
Representando Listas Encadeadas na
Memria
info3
NULL
info2
112
124
info1100
104
108
112
116
120
124
128
Memria
Lista* inicio;
inicio
100
info
prox
info1
inicio
p
r
o
x
info2
p
r
o
x
info3
7/25/2019 19 - aulaIP-ListaEncadeada
10/37
10
Insero de Elementos em Listas
Encadeadas
Diferentes formas de inserir um elemento nalista:
No comeo
Mais simples
No fim
Neste caso deve-se percorrer a lista toda
7/25/2019 19 - aulaIP-ListaEncadeada
11/37
11
Inserindo Elementos no Incio de
Listas Encadeadas
/* insero incio da lista */Lista* lst_insere(Lista* inicio,int i){Lista* novo = (Lista*) malloc(sizeof(Lista));novo->info = i ;
novo->prox = inicio ;return novo ;
}
info1
inicio
info2 info3 info4
Novo
Endereo docomeo da
listaRetorna endereoinicial atualizado
7/25/2019 19 - aulaIP-ListaEncadeada
12/37
12
Inserindo Elementos no Fim de Listas
Encadeadas
/* insero fim da lista */Lista* lst_insere(Lista* inicio,int i){Lista* novo = (Lista*) malloc(sizeof(Lista));novo->info = i ;novo->prox = NULL ;
if (inicio == NULL){inicio = novo;} else {
Lista* p = inicio;while (p->prox != NULL){
p = p->prox;}
p->prox = novo;}return inicio ;
}
Se lista estiver vazia,
iniciovai guardarendereo de novo
Seno temos que percorrer listaat ltimo n, para faz-lo
apontar para novo
7/25/2019 19 - aulaIP-ListaEncadeada
13/37
13
Usando Funo de Insero de Listas
Encadeadas
int main() {Lista* inicio;inicio = NULL;inicio = lst_insere(inicio,23); /* insere 23 */inicio = lst_insere(inicio,45); /* insere 45 */
...return 0 ;}
No esquecer de atualizar avarivel que guarda endereo
inicial da lista a cada insero!
Variavel que armazena endereo inicialda lista deve ser inicializada comNULL!
7/25/2019 19 - aulaIP-ListaEncadeada
14/37
14
Imprimindo Listas Encadeadas
void lst_imprime(Lista* inicio){Lista* p; /*varivel auxiliar para percorrer a
lista */for(p = inicio; p != NULL; p = p->prox){
printf ( info = %d\n , p->info ) ;}
}
Lao para percorrer todos os nsda lista
7/25/2019 19 - aulaIP-ListaEncadeada
15/37
15
Verificando se a Lista Est Vazia
/* funo vazia: retorna 1 se vazia ou 0 se novazia */int lst_vazia(Lista* inicio){int vazio = 0;if (inicio == NULL)
vazio = 1;return vazio;}
/* verso compacta da funo lst_vazia */int lst_vazia ( Lista* inicio ){return(inicio == NULL) ;
}
7/25/2019 19 - aulaIP-ListaEncadeada
16/37
16
Buscando um Elemento em Listas
Encadeadas
Lista* lst_busca(Lista* inicio,int v){int achou = 0;Lista* p = inicio ;
while (p != NULL && !achou) {if (p->info == v)
achou = 1 ;elsep = p->prox;
}return p;
}
Retorna o endereodo primeironque contm o elemento
buscado
Se no achouelemento, retornao endereo nulo!
7/25/2019 19 - aulaIP-ListaEncadeada
17/37
17
Removendo Elementos de Listas
Encadeadas
Dois casos devem ser tratados para a remoo deum elemento da lista
info1
inicio
info2 info3 info4
Remoo do primeiro elemento da lista
info1
inicio
info2 info3 info4
Remoo de um elemento no meio da lista
7/25/2019 19 - aulaIP-ListaEncadeada
18/37
18
Removendo Elementos de Listas
EncadeadasLista* lst_retira(Lista* inicio,int v){Lista* ant = NULL; /* guarda elemento anterior */Lista* p = inicio;
while(p != NULL && p->info != v){ant = p ;
p = p->prox ;
}/* verifica se achou o elemento */if (p != NULL) {
if (ant == NULL)inicio = p->prox;
elseant->prox = p->prox;
free(p) ;}return inicio ;
}
Procura elementona lista,guardando
endereo do
anterior
Retorna endereo inicial da lista
Elemento no inicio, retiraelemento do incio
Retira elemento do meio
7/25/2019 19 - aulaIP-ListaEncadeada
19/37
19
Liberando Listas Encadeadas
void lst_libera(Lista* inicio){Lista* p = inicio ;Lista* t;
while(p != NULL ) {
t = p->prox;free(p); /* libera a memria apontada por p*/p = t; /* faz p apontar para o prximo */
}}
Guarda o endereodo prximon para poder libera-lo na
prxima iterao
7/25/2019 19 - aulaIP-ListaEncadeada
20/37
20
Comparando Listas Encadeadas
int lst_igual(Lista* lst1,Lista* lst2){Lista* p1 ;Lista* p2 ;int igual = 1for(p1 = lst1,p2 = lst2; p1!=NULL && p2!=NULL && igual;
p1=p1->prox,p2=p2->prox){
if(p1->info!= p2->info )igual = 0;
}return(p1 == p2 && igual) ;
}Se os elementos testados foremiguais, deve-se ainda ver sep1ep2apontam paraNULL(tamanhos
das listas iguais)
7/25/2019 19 - aulaIP-ListaEncadeada
21/37
21
Utilizando Funes de Manipulao de
Lista de Inteiros
#include #include lista.hint main() {
Lista * ls ; /* declara uma lista no iniciada */ls = NULL; /*inicia lista vazia */ls = lst_insere(ls,23); /* insere o elemento 23 */
ls = lst_insere(ls,45); /* insere o elemento 45 */ls = lst_insere(ls,56); /* insere o elemento 56 */ls = lst_insere(ls,78); /* insere o elemento 78 */lst_imprime(ls); /* imprime: 78 56 45 23 */ls = lst_retira(ls,78);
lst_imprime(ls); /* imprime: 56 45 23 */ls = lst_retira(ls,45);lst_imprime(ls); /* imprime: 56 23 */lst_libera(ls);return 0 ;
}
7/25/2019 19 - aulaIP-ListaEncadeada
22/37
22
Listas podem variar quanto ao:Tipo de encadeamento
Simples
CircularesDuplas
Circulares e Duplas
Contedo
Tipos PrimitivosTipos Estruturados
Variaes de Listas Encadeadas
J vimosanteriormente
7/25/2019 19 - aulaIP-ListaEncadeada
23/37
2323
Listas Circulares
lista
info1 info3info2
Estrutura do n da lista idntica a da lista
simplesmente endadeadaNo h noo de primeiro e ltimo n da lista
Para saber se toda lista foi percorrida deve-se
guardar o endereo do primeiro n a ser lido e
comparar com o endereo do n que est sendo lido
7/25/2019 19 - aulaIP-ListaEncadeada
24/37
2424
Imprimindo uma Lista Circular
void lcirc_imprime (Lista* inicio) {Lista* p = inicio; /* faz p apontar para on inicial *//* testa se lista no vazia*/if (p != NULL){
do {printf(%d\n,p->info);p = p->prox;
} while (p != inicio);
}A condio de parada dolao quando o n a serpercorrido for igual ao n
inicial
7/25/2019 19 - aulaIP-ListaEncadeada
25/37
25
Lista duplamente encadeada
inicio
info1 info3info2
Permite percorrer a lista em dois sentidos
Cada elemento deve guardar os endereos do
prximo elemento e do elemento anterior
Facilita percorrer a lista em ordem inversa
Retirada de elemento cujo endereo conhecido se
torna mais simples
Acesso ao n anterior para ajustar encadeamento no
implica em percorrer a lista toda
info4
7/25/2019 19 - aulaIP-ListaEncadeada
26/37
26
Estrutura de Listas Duplamente
Encadeadas
inicio
struct lista2 {int info ;
struct lista2* prox;
struct lista2* ant;} ;typedef struct lista2 Lista2 ;
Armazena oendereo doprximo n fim
info1
p
ro
x
a
nt
info1
p
ro
x
info1
a
n
t
Armazena oendereo don anterior
7/25/2019 19 - aulaIP-ListaEncadeada
27/37
2727
inicio
info1 info3info2
novo
Inserindo Elementos no Incio de
Listas Duplamente Encadeadas
Lista2* lst2_insere (Lista2* inicio, int v) {
Lista2* novo = (Lista2*) malloc(sizeof(Lista2));
novo->info = v; novo->prox = inicio;
novo->ant = NULL;/* verifica se lista no est vazia */
if (inicio != NULL)
inicio->ant = novo;
return novo;
}
Insero no comeo da lista
7/25/2019 19 - aulaIP-ListaEncadeada
28/37
2828
inicio
info1 info3info2
novo
Insero no fim da lista
Inserindo Elementos no Fim de Listas
Duplamente Encadeadas
7/25/2019 19 - aulaIP-ListaEncadeada
29/37
2929
Inserindo Elementos no Fim de Listas
Duplamente Encadeadas
Lista2* lst2_insere (Lista2* inicio, int v) {
Lista2* novo = (Lista2*) malloc(sizeof(Lista2));
novo->info = v; novo->prox = NULL;
if (inicio == NULL) {
novo->ant = NULL;
inicio = novo} else {
Lista2* p;
while (p->prox != NULL) [
p = p->prox;
}p->prox = novo;
novo->ant = p;
}
return inicio;
}
Se lista estiver vazia,
endereo do n anterior anovo NULL
Seno temos que fazer com que o ltimon aponte para novo e n anterior de
novo seja o antigo ltimo n
7/25/2019 19 - aulaIP-ListaEncadeada
30/37
30
Lista2* lst_busca (Lista2* lista, int v)
{Lista2* p;
int achou = 0
for (p = lista; p != NULL && !achou; p = p->prox)
if (p->info == v)achou = 1;
return p;
}
Buscando um Elemento em Listas
Duplamente Encadeadas
Mesma lgica aplicada a listas simplesmenteencadeadas
7/25/2019 19 - aulaIP-ListaEncadeada
31/37
31
Removendo Elementos de Listas
Duplamente EncadeadasTrs casos devem ser tratados para a remoo de
um elemento da lista
Remoo de um elemento no meio da lista
info1
inicio
info2 info3 info4
info1
inicio
info2 info3 info4
Remoo de um elemento do fim da lista
info1
inicio
info2 info3 info4
Remoo do primeiro elemento da lista
R d El t d Li t
7/25/2019 19 - aulaIP-ListaEncadeada
32/37
32
Lista2* lst2_retira (Lista2* inicio, int v) {
Lista2* p = busca(inicio, v);
if (p != NULL){
if (inicio == p)
inicio = p->prox;
elsep->ant->prox = p->prox;
if (p->prox != NULL)
p->prox->ant = p->ant;
free(p);}
return inicio;
}
Removendo Elementos de Listas
Duplamente Encadeadas
Usando a funode busca
Retira elemento do
comeo da lista
Retira do meio
S acerta o encadeamento do ponteiropara o anterior se NOfor o ltimo
elemento
Li t Ci l D l t
7/25/2019 19 - aulaIP-ListaEncadeada
33/37
33
lista
info1 info3info2
Lista Circular Duplamente
Encadeada
Permite percorrer a lista nos dois sentidos, apartir de um ponteiro para um elemento
qualquer
I i i d S tid I
7/25/2019 19 - aulaIP-ListaEncadeada
34/37
3434
void l2circ_imprime_inverso (Lista2* lista){
Lista2* p = lista;
if (p != NULL)do {
p = p->ant;
printf(%d\n,p->info);
} while (p != lista);
}
Imprimindo no Sentido Inverso com
um Lista Circular Duplamente
Encadeada
Avana para o nanterior
7/25/2019 19 - aulaIP-ListaEncadeada
35/37
35
typedef struct retangulo {
float b; /* base */
float h; /* altura */
} Retangulo;
Lista de Tipos Estruturados
Uma lista pode ser composta de elementos estruturados
Considere o tipo Retangulo
OU
typedef struct lista {
Retangulo info;
struct lista *prox;
} Lista;
Podemos definir uma lista cujos ns contenham ouum
retngulo ouum ponteiro para um retngulo
typedef struct lista {
Retangulo* info;
struct lista *prox;
} Lista;
I i d N Li t d
7/25/2019 19 - aulaIP-ListaEncadeada
36/37
36
Lista* insere (Lista* inicio,float b, float h) {
Lista *novo;
novo = (Lista*)malloc(sizeof(Lista));
novo->info.b = b;
novo->info.h = h;
novo->prox = inicio
return novo;}
Inserindo um N em uma Lista de
Tipos Estruturados
N da lista contm um retngulo
I i d N d Li t d Ti
7/25/2019 19 - aulaIP-ListaEncadeada
37/37
37
Inserindo um N de uma Lista de Tipos
Estruturados
Lista* insere (Lista* inicio,float b, float h){Retangulo *r;
r = (Retangulo*) malloc(sizeof(Retangulo));Lista* novo = (Lista*)malloc(sizeof(Lista));r->b = b;r->h = h;novo->info = r;novo->prox = inicio;return novo;
}
N da lista contm um ponteiro para um retngulo
Espao para a estruturaRetangulodeve tambm seralocado