listas lineares encadeadas possuem algumas …200 listas circulares listas lineares encadeadas...

30
200 Listas Circulares Listas lineares encadeadas possuem algumas deficiências. Como, por exemplo, dado um ponteiro p para um nodo de uma lista linear encadeada, não podemos atingir nenhum nodo que antecede o apontado por p. Contudo, se fizermos uma pequena alteração na estrutura de lista que temos trabalhado, fazendo com que o campo next do último nodo ao invés de conter NULL armazene o endereço do primeiro nodo da lista.

Upload: others

Post on 09-Jul-2020

69 views

Category:

Documents


0 download

TRANSCRIPT

200

Listas Circulares

Listas lineares encadeadas possuem algumas deficiências. Como, por exemplo, dado um ponteiro p para um nodo de uma lista linear encadeada, não podemos atingir nenhum nodo que antecede o apontado por p.

Contudo, se fizermos uma pequena alteração na estrutura de lista que temos trabalhado, fazendo com que o campo next do último nodo ao invés de conter NULL armazene o endereço do primeiro nodo da lista.

201

Listas Circulares

Este tipo de lista é denominado lista circular, possuindo a forma abaixo:

Uma pergunta surge: para qual elemento apontar para que se tenha uma referência a lista circular?

Nodo 3Nodo 1 Nodo 2Nodo 4

202

Listas Circulares

Uma convenção útil é fazer com que o ponteiro esterno para a lista circular aponte para o último elemento.

Pois desta forma se tem acesso direto ao último e primeiro elemento.

Nodo 3Nodo 1 Nodo 2

L

Nodo 4

203

Listas Circulares

Como podemos observar a definição do TAD LISTA_CIRCULAR é praticamente a mesma do TAD LISTA_ENC, apenas algumas pequenas alterações são necessárias nas operações.

204

typedef struct nodo{

int inf;struct nodo * next;

}NODO;typedef NODO * LISTA_CIRCULAR;void cria_lista (LISTA_CIRCULAR *);int eh_vazia (LISTA_CIRCULAR);int tam (LISTA_CIRCULAR);void ins (LISTA_CIRCULAR *, int, int);int recup (LISTA_CIRCULAR, int);void ret (LISTA_CIRCULAR *, int);

205

void cria_lista (LISTA_CIRCULAR *pl){

*pl=NULL;}

int eh_vazia (LISTA_CIRCULAR l){

return (l == NULL);}

206

int tam (LISTA_CIRCULAR l){

if (l==NULL)return (0);

else{

LISTA_CIRCULAR aux;int cont;for (cont=1, aux=l->next; aux!=l ;

cont++)aux = aux->next;

return (cont); } }

207

Esquema do processo da inserção de um nó da lista circular. (situação um)

L

Listas Circulares

Novo

v.

L

Nodo 1

v.

208

Esquema do processo da inserção de um nó da lista circular. (situação dois)

X

Nodo 3Nodo 1 Nodo 2

L

Nodo 4

Listas Circulares

NovoX

v

Nodo 3Nodo 1 Nodo 2

L

Nodo 4

Nodo 5

v

209

Esquema do processo da inserção de um nó da lista circular. (situação três)

X

Nodo 3Nodo 1 Nodo 2

L

Nodo 4

Listas Circulares

Novo

v

Nodo 4Nodo 1 Nodo 3

L

Nodo 5

Nodo 2

v

210

void ins (LISTA_CIRCULAR *pl, int v, int k){

NODO *novo;if (k < 1 || k > tam(*pl)+1){printf ("\nERRO! Posição invalida para insercao.\n");exit (1);

}

novo = (NODO *) malloc (sizeof(NODO));if (!novo){

printf ("\nERRO! Memoria insuficiente!\n");exit (2);

}

211

novo->inf = v;if (*pl==NULL) {

novo->next=novo;*pl = novo; }

else{

LISTA_CIRCULAR aux=*pl;if (k==tam(*pl)+1)

*pl=novo;for (; k>1; aux=aux->next, k--);novo->next = aux->next;aux->next = novo; } }

212

int recup (LISTA_CIRCULAR l, int k){

if (k < 1 || k > tam(l)){

printf ("\nERRO! Consulta invalida.\n");exit (3);

}for (;k>0;k--)

l=l->next;return (l->inf);

}

213

Esquema do processo da retirada de um nó da lista circular. (situação um)

LNodo 1

Listas Circulares

.

L .

X

214

Esquema do processo da retirada de um nó da lista circular. (situação dois)

X

Nodo 3Nodo 1 Nodo 2

L

Nodo 4

Listas Circulares

XAux

Nodo 3Nodo 1 Nodo 2

L

215

Esquema do processo da retirada de um nó da lista circular. (situação três)

X

Nodo 3Nodo 1 Nodo 2

L

Nodo 4

Listas Circulares

Aux

Nodo 2Nodo 1

L

Nodo 3

216

void ret (LISTA_CIRCULAR *pl, int k){

if (k < 1 || k > tam(*pl)){printf ("\nERRO! Posição invalida para retirada.\n");exit (4);

}

if (tam(*pl)==1){

free (*pl);*pl = NULL;

}

217

else{

NODO *aux, *aux2;int i;for (aux=*pl, i=k; i>1; i--, aux=aux->next);aux2 = aux->next;aux->next = aux2->next;if (k==tam(*pl))

*pl=aux;free (aux2);

}}

218

Listas Circulares – Nó de Cabeçalho

O conceito de nó de cabeçalhotambém pode ser empregado nas listas circulares. Por exemplo, podemos utilizar o nó de cabeçalho como um ponto de verificação para testar se alista inteira foi atravessada.

A implementação de um TAD LISTA_CIRCULAR_COM_NC é sugerida como uma exercício de fixação.

219

Listas Duplamente Encadeadas

Como vimos, uma lista circular possui vantagens sobre uma lista linear, contudo esta ainda possui limitações. Por exemplo, não podemos percorrê-la no sentido contrário ou ainda para inserirmos ou retirarmos um k-ésimoelemento temos que ter um ponteiro para seu antecessor.

Com o objetivo de sanar estas limitações surgiram as listas duplamente encadeadas.

220

Listas Duplamente Encadeadas

Em uma lista duplamente encadeadaos elementos possuem três campos: o campo inf o qual contém a informação, o campo ant que possui um ponteiro para o elemento antecessor e o campo prox que é uma referência para o elemento que sucede.

L

λλλλ

ant

λλλλ

prox

inf

221

Listas Duplamente EncadeadasDefiniremos agora o TAD LISTA_DUP_ENC:typedef struct nodo{

int inf;struct nodo * ant;struct nodo * prox;

}NODO;typedef NODO * LISTA_DUP_ENC;void cria_lista (LISTA_DUP_ENC *);int eh_vazia (LISTA_DUP_ENC);int tam (LISTA_DUP_ENC);void ins (LISTA_DUP_ENC *, int, int);int recup (LISTA_DUP_ENC, int);void ret (LISTA_DUP_ENC *, int);

222

void cria_lista (LISTA_DUP_ENC *pl){

*pl=NULL;}int eh_vazia (LISTA_DUP_ENC l){

return (l == NULL);}int tam (LISTA_DUP_ENC l){

int cont;for (cont=0; l!= NULL; cont++)

l = l->prox;return (cont); }

223

Esquema do processo da inserção de um nó da lista duplamente encadeada. (situação um)

Listas Duplamente Encadeadas

L

Novo

v. . .

L

Nodo 1

v. . .

224

Esquema do processo da inserção de um nó da lista duplamente encadeada. (situação dois)

Listas Duplamente Encadeadas

L

Nodo 1 Nodo 2 Nodo 3

Novo

v

..

.X

L

Nodo 2 Nodo 3 Nodo 4

Nodo 1

v

..

.

225

Esquema do processo da inserção de um nó da lista duplamente encadeada. (situação três)

Listas Duplamente Encadeadas

L

Nodo 1 Nodo 2

Novo

v

..

.

L

Nodo 1 Nodo 2

Nodo 3

v

..

.

226

Esquema do processo da inserção de um nó da lista duplamente encadeada. (situação quatro)

Listas Duplamente Encadeadas

L

Nodo 1 Nodo 2 Nodo 3

Novo

v

.. XX

L

Nodo 1 Nodo 3 Nodo 4

Nodo 2

v

..

227

void ins (LISTA_DUP_ENC *pl, int v, int k){

NODO *novo;if (k < 1 || k > tam(*pl)+1){

printf ("\nERRO! Posição invalida parainsercao.\n");exit (1);

}novo = (NODO *) malloc (sizeof(NODO));if (!novo){

printf ("\nERRO! Memoria insuficiente!\n");exit (2); }

228

novo->inf = v;if (k==1){

novo->ant = NULL;novo->prox = *pl;*pl = novo;if ((*pl)->prox)

(*pl)->prox->ant=novo;}else{

LISTA_DUP_ENC aux;for (aux=*pl; k>2; aux=aux->prox, k--);

229

novo->prox = aux->prox;aux->prox = novo; novo->ant=aux;if (novo->prox)

novo->prox->ant=novo;}

}