Você está na página 1de 23

28/01/2016

Estruturas de Dados

Listas, pilhas e filas dinâmicas

1 Prof. Luciana Rocha Cardoso

Listas dinâmicas

2 Prof. Luciana Rocha Cardoso

1
28/01/2016

Listas dinâmicas
 Quando o TAD Lista é implementado de forma estática,
corre-se o risco de sub/superdimensionamento do uso
da memória (arranjo alocado).
 Para melhor gerenciar o uso de memória, ou seja, alocar
apenas a memória que for de fato utilizada, lança-se mão
do recurso de alocação dinâmica para implementar o
TAD lista, resultando nas chamadas listas dinâmicas.
 Assim, quando for necessário inserir um elemento na
lista, basta alocar a quantidade de memória necessária e
referenciar a região alocada através de ponteiros. Sob o
mesmo raciocínio, ao remover um elemento da lista, a
região de memória ate então utilizada deve ser
devidamente desalocada.
Prof. Luciana Rocha Cardoso
3

Listas dinâmicas
 O encadeamento da lista será feito, portanto,
por ponteiros. No caso de listas simplesmente
encadeadas, cada elemento referencia a região
de memória onde se encontra seu sucessor.
 A seguir, é dada uma estrutura de dados em C++
para representar uma lista dinâmica de números
inteiros simplesmente encadeada.
 Note que agora adicionaremos as funções
criaNodo e destroi para alocar espaço para um
nodo e desalocar todo o espaço ocupado pela
lista, respectivamente.
4 Prof. Luciana Rocha Cardoso

2
28/01/2016

LSED – Lista Simplesmente Encadeada Dinâmica

struct NodoLista {
int info;
NodoLista* prox;
};
struct Lista {
NodoLista* primeiro;
int tam;
};

5 Prof. Luciana Rocha Cardoso

LSED – Lista Simplesmente Encadeada Dinâmica


// Cria lista vazia
void fazListaVazia(Lista& l) {
l.primeiro = NULL;
l.tam = 0;
}
// Testa se lista vazia
int listaVazia(const Lista& l) {
return ( l.primeiro == NULL );
}
// Testa se pos representa fim da lista
int fimLista(const Lista& l, NodoLista* pos){
return ( pos == NULL ); //l soh eh passa-
} // da para abarcar possiveis modificacoes

6 Prof. Luciana Rocha Cardoso

3
28/01/2016

LSED – Lista Simplesmente Encadeada Dinâmica


// Retorna tamanho da lista
int tamanhoLista(const Lista& l) {
return ( l.tam );
}
// retorna ponteiro para o primeiro elemento
NodoLista* primeiroDaLista(const Lista& l) {
return ( l.primeiro );
}

7 Prof. Luciana Rocha Cardoso

LSED – Lista Simplesmente Encadeada Dinâmica


// Aloca memoria para um determinado NODO e
// retorna o apontador para este NODO.
// Se nao for possível alocar memoria,
// retorna NULL
NodoLista* criaNodo(int e) {
NodoLista* aux;
aux = new NodoLista;
if (aux != NULL)
aux->info = e;
return aux; // lembre-se, new retorna NULL
// se nao hah memoria disponivel.
}

8 Prof. Luciana Rocha Cardoso

4
28/01/2016

LSED – Lista Simplesmente Encadeada Dinâmica


void destroiNodo(NodoLista* p) {
if ( p!=NULL ) // ou simplesmente if ( p )
delete p;
}
// Insere o novo NODO na PRIMEIRA posicao da lista
int insereInicio(Lista& l, NodoLista* novo) {
if ( novo != NULL ) {
novo->prox = l.primeiro;
l.primeiro = novo;
l.tam++;
return 1; // sucesso
}
return 0; // insucesso
}

9 Prof. Luciana Rocha Cardoso

LSED – Lista Simplesmente Encadeada Dinâmica


// Insere o NODO como ultimo elemento
int insereFim(Lista& l, NodoLista* novo) {
NodoLista* aux;
if ( novo==NULL ) return 0; // insucesso
novo->prox = NULL;
if ( listaVazia(l) ) {
l.primeiro = novo;
l.tam++;
return 1;
}
aux = primeiroDaLista(l);
while ( aux->prox )
aux = aux->prox;
aux->prox = novo;
l.tam++;
return 1; // sucesso
}
10 Prof. Luciana Rocha Cardoso

5
28/01/2016

LSED – Lista Simplesmente Encadeada Dinâmica

// Insere um elemento depois do nodo


// apontado por p
int insere(Lista& l, NodoLista* p, NodoLista* novo) {
if ( p != NULL && novo != NULL ) {
// ou if ( p && novo )
novo->prox = p->prox;
p->prox = novo;
l.tam++;
return 1; // sucesso
}
return 0; // insucesso
}

11 Prof. Luciana Rocha Cardoso

LSED – Lista Simplesmente Encadeada Dinâmica


// Retira o NODO apontado por pos do encadeamento.
int remove(Lista& l, NodoLista* pos) {
NodoLista* aux;
if (pos==NULL || listaVazia(l)) return 0;
if (pos==primeiroDaLista(l)) l.primeiro=pos->prox;
else {
aux = primeiroDaLista(l);
while ( !fimLista(l,aux) && aux->prox != pos )
aux = aux->prox;
if ( !fimLista(l,aux) )
aux->prox = pos->prox;
else return 0;
}
l.tam--;
return 1; // sucesso
}
12 Prof. Luciana Rocha Cardoso

6
28/01/2016

LSED – Lista Simplesmente Encadeada Dinâmica

// Localiza um elemento na lista.


// Retorna a posição onde o elemento
// se encontra ou NULL caso o elemento
// nao esteja na lista.
NodoLista* localiza(const Lista& l, int e){
// *** Fica como exercicio ***
}
// Imprime todos os elementos da Lista
void imprime(const Lista& l) {
// *** Fica como exercicio ***
}

13 Prof. Luciana Rocha Cardoso

LSED – Lista Simplesmente Encadeada Dinâmica


// Destroi a lista, ou seja, libera
// toda a memoria ocupada pela mesma.
// Percorre a lista removendo sempre
// o primeiro elemento.
void destroi(Lista& l) {
NodoLista* aux = primeiroDaLista( l );
while ( !fimLista(l,aux) ) {
remove(l,aux); // Aqui soh retira nodo
// do encadeamento.
delete aux; //Aqui sim libera a memoria
// usada pelo nodo.
aux = primeiroDaLista( l );
}
}

14 Prof. Luciana Rocha Cardoso

7
28/01/2016

LSED – Lista Simplesmente Encadeada Dinâmica


void main(){ //Um programinha exemplificando o uso
NodoLista* p;
Lista l1;
fazListaVazia(l1);
// Inserir o elemento 1 na Lista Vazia
insereFim( l1, criaNodo(1) ); // Ou insereInicio
// Inserir o elemento 2 depois do 1
insere( l1, localiza(l1,1), criaNodo(2) );
// Inserir o elemento 3 depois do 2
insere( l1, localiza(l1,2), criaNodo(3) );
// Inserir o elemento 4 depois do 3
insereFim( l1, criaNodo(4) );
...

15 Prof. Luciana Rocha Cardoso

LSED – Lista Simplesmente Encadeada Dinâmica

...
// Inserir o elemento 6 depois do 4
insereFim( l1, criaNodo(6) );
// Inserir o elemento 0 na primeira posicao
insereInicio( l1, criaNodo(0) );
// Inserir o elemento 5 depois do 4
insere( l1, localiza(l1,4), criaNodo(5) );
imprime(l1);
cout<<"\nTamanho: "<<tamanhoLista(l1)<<"\n\n";
...

16 Prof. Luciana Rocha Cardoso

8
28/01/2016

LSED – Lista Simplesmente Encadeada Dinâmica


...// Remover o elemento 3
p=localiza(l1,3);
remove( l1, p );
destroiNodo(p);
// Remover elemento 0
p=localiza(l1,0);
remove( l1, p );
destroiNodo(p);
// Remover elemento 5
p=localiza(l1,5);
remove( l1, p );
destroiNodo(p);
imprime( l1 );
cout<<"\nTamanho: "<<tamanhoLista(l1)<<"\n\n";
destroi( l1 );
}

17 Prof. Luciana Rocha Cardoso

Exercícios
 1) Acrescente a implementação vista uma função
para inserir ordenadamente.
 2) Faça as funções que faltam.

18 Prof. Luciana Rocha Cardoso

9
28/01/2016

LSEDD
 Mostrar códigos .

19 Prof. Luciana Rocha Cardoso

Pilhas dinâmicas

20 Prof. Luciana Rocha Cardoso

10
28/01/2016

Pilha dinâmica
 O conceito de pilha na implementação a seguir será de
um ponteiro que sempre aponta para o nodo no topo da
pilha.
 Alem disto, cada nodo terá um apontador que indicara o
nodo imediatamente abaixo na pilha.

 A pilha vazia será representada pelo ponteiro topo


apontando para NULL.

21 Prof. Luciana Rocha Cardoso

Pilha dinâmica
 Ao empilhar um novo
nodo, o topo passará a
apontar para este nodo e
o sucessor do novo nodo
será o antigo topo:

 Ao desempilhar, o topo
passará a apontar para o
nodo imediatamente
abaixo do antigo topo.

22 Prof. Luciana Rocha Cardoso

11
28/01/2016

Pilha dinâmica
 Passemos agora para uma implementação em C++
de uma pilha dinâmica de inteiros.
struct NodoPilha {
int info;
NodoPilha* prox;
};
struct Pilha {
NodoPilha* topo;
};

23 Prof. Luciana Rocha Cardoso

Pilha dinâmica
// Inicia a pilha como vazia
void fazPilhaVazia(Pilha& p) {
p.topo = NULL;
}

// retorna V se pilha vazia e F c.c.


int pilhaVazia(const Pilha& p) {
return ( p.topo == NULL );
}

24 Prof. Luciana Rocha Cardoso

12
28/01/2016

Pilha dinâmica
// Aloca memoria para um nodo e retorna apontador
// para este. Se memoria cheia, retorna NULL
NodoPilha* criaNodo(int e) {
NodoPilha* aux;
aux = new NodoPilha;
if ( aux )
aux->info = e;
return aux;
}

void destroiNodo(NodoPilha* p) {
if ( p )
delete p;
}

25 Prof. Luciana Rocha Cardoso

Pilha dinâmica
// Empilha o nodo n na pilha
int empilha(Pilha& p, NodoPilha* n) {
if ( n != NULL ) {
n->prox = p.topo;
p.topo = n;
return 1;
}
return 0;
}

26 Prof. Luciana Rocha Cardoso

13
28/01/2016

Pilha dinâmica
// Retira o elemento que se encontra no topo
// da pilha e retorna um ponteiro para o
// mesmo
NodoPilha* desempilha(Pilha& p) {
// *** Fica como exercicio ***
}
// Retorna o ponteiro para o topo,
// sem desempilhar.
NodoPilha* obtemTopo(const Pilha& p) {
// *** Fica como exercicio ***
}

27 Prof. Luciana Rocha Cardoso

Pilha dinâmica
void imprime(Pilha* p) {
// *** Fica como exercicio ***
}
// Desaloca toda a memoria ocupada pelos
// nodos da pilha
void destroi(Pilha* p) {
// *** Fica como exercicio ***
}

28 Prof. Luciana Rocha Cardoso

14
28/01/2016

Pilha dinâmica
// Um pequeno programa para demonstrar o uso
void main () {
Pilha p;
NodoPilha* n;
fazPilhaVazia(p);
n = criaNodo(1); // Empilha o elemento 1
empilha(p,n);
n = criaNodo(2); // Empilha o elemento 2
empilha(p,n);
n = criaNodo(3); // Empilha o elemento 3
empilha(p,n);
imprime(p); // Resultado 3 2 1
...
29 Prof. Luciana Rocha Cardoso

Pilha dinâmica
...
n = desempilha(p);
if ( n ) {
cout<<"\nAntigo topo = "<<n->info<<"\n\n";// 3
destroiNodo(n);
}
imprime(p); // Resultado 2 1
n = obtemTopo(p);
if ( n != NULL )
cout<<"\nTopo = "<<n->info<<"\n\n";// Topo = 2
imprime(p); // Resultado 2 1
cout << "\n\n";
...

30 Prof. Luciana Rocha Cardoso

15
28/01/2016

Pilha dinâmica
...
n = criaNodo(4); // Empilha o elemento 4
empilha(p,n);
imprime(p); // Resultado 4 2 1
destroi(p);
}

31 Prof. Luciana Rocha Cardoso

Exercícios
 Utilize a pilha que acabamos de ver para resolver os
exercícios abaixo:
1) Faca um programa em C++ para converter um numero
decimal em binário, utilizando uma pilha dinâmica de
inteiros para empilhar os restos das divisões por dois
necessárias para a conversão.
2) Escreva um programa que utilize uma pilha dinâmica
para verificar se expressões aritméticas estão com a
“parentetização” correta. Seu programa deve checar as
expressões para ver se cada "abre parênteses" possui um
"fecha parênteses" correspondente.

32 Prof. Luciana Rocha Cardoso

16
28/01/2016

Filas dinâmicas

33 Prof. Luciana Rocha Cardoso

Filas dinâmicas
 Na versão dinâmica, o tipo que representa fila será
composto por um ponteiro para o inicio da fila e
outro para o final. Cada nodo terá um ponteiro que
referencia seu sucessor na fila.

 A fila vazia será representada pelos ponteiros inicio e


fim apontando para NULL.

34 Prof. Luciana Rocha Cardoso

17
28/01/2016

Filas dinâmicas
 Ao enfileirar um novo nodo,
o ponteiro fim passará a
apontar para este nodo e o
sucessor do novo nodo será
NULL:

 Ao desenfileirar, o ponteiro
inicio passara a apontar para
o sucessor do nodo
desenfileirado:

35 Prof. Luciana Rocha Cardoso

Filas dinâmicas
 Passemos agora para uma implementação em C++
de uma fila dinâmica de inteiros.
struct NodoFila {
int info;
NodoFila* prox;
};
struct Fila {
NodoFila* inicio;
NodoFila* fim;
};

36 Prof. Luciana Rocha Cardoso

18
28/01/2016

Filas dinâmicas
// Inicia a fila como vazia
void fazFilaVazia(Fila& f) {
f.inicio = NULL;
f.fim = NULL;
}
// retornaV se fila vazia e F c.c.
int filaVazia(const Fila& f) {
return ( f.inicio == NULL && f.fim == NULL);
}

37 Prof. Luciana Rocha Cardoso

Filas dinâmicas
// Aloca memoria para um nodo e retorna apontador
// para este. Se memoria cheia, retorna NULL
NodoFila* criaNodo(int e) {
NodoFila* aux = new NodoFila;
if ( aux != NULL )
aux->info = e;
return aux;
}
void destroiNodo(NodoFila* p) {
if( p ) delete p;
}

38 Prof. Luciana Rocha Cardoso

19
28/01/2016

Filas dinâmicas
// Enfileira nodo apontado por n
int enfileira(Fila& f, NodoFila* n) {
if ( n != NULL ) {
n->prox = NULL;
// Verifica se a fila esta vazia
if ( filaVazia(f) ) {
f.inicio = f.fim = n;
}
else {
f.fim->prox = n;
f.fim = n;
}
return 1;
}
return 0;
}
39 Prof. Luciana Rocha Cardoso

Filas dinâmicas
// Retorna o apontador para o elemento que esta
// na frente da fila, sem desenfileira-lo
NodoFila* frenteFila(const Fila& f) {
return f->inicio;
}
NodoFila* desenfileira(Fila& f) {
// *** Fica como exercicio ***
}
void destroi(Fila& f) {
// *** Fica como exercicio ***
}

40 Prof. Luciana Rocha Cardoso

20
28/01/2016

Filas dinâmicas
void main () {
Fila f;
NodoFila* n;
fazFilaVazia(f);
n = criaNodo(1);
enfileira(f,n); // Enfileira 1
n = criaNodo(2);
enfileira(f,n); // Enfileira 2
n = criaNodo(3);
enfileira(f,n); // Enfileira 3
imprime(f); // Resultado 1 2 3
...

41 Prof. Luciana Rocha Cardoso

Filas dinâmicas
...
n = frenteFila(f);
if ( n != NULL ) {
cout<<"\nFrente="<<n->info<<"\n";//Frente = 1
}
n = desenfileira(f);
if ( n != NULL ){
cout<<"\nFrente antiga="<<n->info<<"\n"; // 1
destroiNodo(n);
}
imprime(f); // Resultado 2 3
...

42 Prof. Luciana Rocha Cardoso

21
28/01/2016

Filas dinâmicas
...
n = criaNodo(4);
enfileira(f,n); // Enfileira 4
imprime(f); // Resultado 2 3 4
n = frenteFila(f);
if ( n != NULL ) {
cout<<"\nFrente="<<n->info<<"\n";// Frente
=2
}
destroi(f);
}

43 Prof. Luciana Rocha Cardoso

Exercícios
1) Desenvolva um programa em C++, utilizando fila
dinâmica, que permita gerir uma pista para decolagem
de aviões de um aeroporto. Para o correto
funcionamento desta pista e necessário que sejam
implementadas as seguintes funcionalidades:
• No de aviões a espera de decolar.
• Decolagem de um avião.
• Entrada de um novo avião para decolar.
• Listar todos os aviões (nome e numero) a espera de
decolar.
• Listar as características (nome e numero) do próximo
avião a decolar.

44 Prof. Luciana Rocha Cardoso

22
28/01/2016

Exercícios
2) Faca o exercício abaixo, ja solicitado quando vimos
filas e pilhas estáticas, mas desta vez utilize fila e
pilha dinâmicas.
Suponha que tenhamos um programa em C++ para
armazenar uma fila de pessoas (nome das pessoas).
Tendo em vista o ditado "os últimos serão os primeiros",
crie uma função que pegue a fila e a inverta, ou seja,
quem estava no início da fila vai passar a estar no final e
quem estava no final passará a estar no início. Utilize
uma pilha para esta inversão. Veja, portanto, que você
terá que adaptar as filas e pilhas que vimos para
acomodarem strings (os nomes).

45 Prof. Luciana Rocha Cardoso

Exercícios
 3) Pesquise e descreve a estrutura de dados hash.

46 Prof. Luciana Rocha Cardoso

23