Sei sulla pagina 1di 71

Ps-Graduao em Cincias da Computao

Anlise de Algoritmos e Estrutura de Dados


UFABC
Universidade Federal do ABC
Prof. Andr G. R. Balan
andre.balan@ufabc.edu.br
Aula 03
Pilhas
Sequencial
Encadeada
Aplicaes
Contedo
2
Estruturas de dados
Para explicar esse conceito, partimos do princpio que todo
algoritmo manipula dados (entrada e sada)
Uma estrutura de dados consiste em um meio de se armazenar
dados com o objetivo de facilitar ao algoritmo:
Receber novos dados
Encontrar dados que ele precise em um determinado momento
Se livrar de dados no mais relevantes
Introduo
3
Estruturas de dados
Uma estrutura de dados deve especificar:
Uma tcnica para armazenas os dados (sequencial, encadeado
hierrquico, enfileirado, empilhado)
Operaes que podem ser realizada sobre o conjunto de dados
As bsicas so: Insero, Remoo, Busca
Estas mesmas operaes bsicas so aplicadas grande maioria
das estruturas, porm elas funcionam de maneira diferente.
Exemplo: qual a diferena entre enfileirar e empilhar?
Introduo
4
Estruturas de dados
Uma estrutura de dados pode ser projetada para armazenar
dados em diversas meios de armazenamento:
Disco
Fita
Memria principal (interna)
Nesta disciplina estudaremos em primeiro plano
as estruturas de dados para memria principal
Introduo
5
Estruturas de dados elementares (lineares)
Pilhas
Filas
Listas
Mtodos de implementao
Sequencial
Encadeado
Introduo
6
Uma pilha sequencial uma ED implementada em cima
de um vetor de dados. Os elementos da pilha ocuparo
posies contguas de memria, por isso o termo
senquencial.
As duas principais operaes so
Empilha / Push
Desempilha / Pop
Essas duas operaes operam somente em uma posio da pilha:
o topo
Pilha sequencial (sequential stack)
7
O ltimo elemento empilhado sempre o primeiro a
ser desempilhado
Por isso, a pilha tambm chamada de estrutura LIFO
(Last In, First Out)
Pilha sequencial
8
Vamos supor uma pilha sequencial de
inteiros
Inicialmente, alocamos um vetor como
desejarmos: alocao esttica (stack) ou
dinmica (heap)
Vamos preferir alocao dinmica
Pilha sequencial
0
1
n-1
.
.
.
9
Inicialmente a pilha est vazia
Precisamos de uma varivel ndice para
determinar o topo da pilha
Pilha sequencial
0
1
n-1
.
.
.
10
Inicialmente a pilha est vazia
Precisamos de uma varivel ndice para
determinar o topo da pilha
Como a pilha est vazia, topo indica
(aponta) para uma posio antes do
comeo do vetor: topo = -1;
Pilha sequencial
0
1
n-1
.
.
.
topo
11
Vamos inserir o inteiro 20
Pilha sequencial
0
1
n-1
.
.
.
topo
12
Primeiro incrementamos de uma unidade
o topo: topo++
Pilha sequencial
0
1
n-1
.
.
.
topo
13
Primeiro incrementamos de uma unidade
o topo: topo++
Em seguida, inserimos o elemento 20,
onde topo est indicando
Pilha sequencial
0
1
n-1
.
.
.
topo
20
14
Agora vamos empilhar outros elementos
Pilha sequencial
0
1
n-1
.
.
.
topo
20
15
Agora vamos empilhar outros elementos
Pilha sequencial
0
1
n-1
.
.
.
topo
20
30
16
Agora vamos empilhar outros elementos
Pilha sequencial
0
1
n-1
.
.
.
topo
20
30
40
17
Mas preciso ter cuidado: o vetor tem uma
quantidade limitada de memria
Um nova insero requer sempre uma
verificao inicial:
topo == n-1 ?
Se sim, a pilha deve avisar o utilizar por meio
de algum mecanismo que a pilha est cheia
Pilha sequencial
0
1
n-1
.
.
.
topo
20
30
40
50
60
70
80
90
100
18
Mecanismos de comunicao ED/utilizador:
Mensagem direta: cout << Pilha cheia
Valor de retorno: return(false);
Mecanismo de excees:
throw logic_error("Pilha cheia");
As excees so a melhor forma de se comunicar
algo ao utilizador da classe. Vamos procurar sempre
utilizar excees
Pilha sequencial
19
Agora vamos desempilhar alguns
elementos
Pilha sequencial
0
1
n-1
.
.
.
topo
20
30
40
50
60
70
80
90
100
20
Agora vamos desempilhar alguns
elementos
Pilha sequencial
0
1
n-1
.
.
.
topo
20
30
40
50
60
70
80
90
100
21
Agora vamos desempilhar alguns
elementos
Pilha sequencial
0
1
n-1
.
.
.
topo
20
30
40
50
60
70
80
90
22
Agora vamos desempilhar alguns
elementos
Tambm preciso tomar cuidado:
Se a pilha estiver vazia, uma tentativa de
desempilhamento deve gerar um aviso ao
utilizador: Pilha vazia
Pilha sequencial
0
1
n-1
.
.
.
topo
20
23
Agora, vamos criar uma classe PilhaSeq para inteiros, em C++
Pilha sequencial
class PilhaSeq {
public:
PilhaSeq(int size);
~PilhaSeq();
// Mtodos principais
void empilha(int elem);
int desempilha();
// Mtodos auxiliares
bool cheia();
bool vazia();
int tamanho();
private:
int *vetor;
int topo, size;
};
P
i
l
h
a
S
e
q
.
h
24
Acontece, que queremos um ED genrica. Vamos utilizar templates
Pilha sequencial
template <typename Tipo>
class PilhaSeq {
public:
PilhaSeq(int size);
~PilhaSeq();
// Mtodos principais
void empilha(const Tipo &elem);
Tipo desempilha();
// Mtodos auxiliares
bool cheia();
bool vazia();
int tamanho();
private:
Tipo *vetor;
int topo, size;
};
P
i
l
h
a
S
e
q
.
h
25
Vamos convensionar que a ED utilizar excees para comunicao
Pilha sequencial
template <typename Tipo>
class PilhaSeq {
public:
PilhaSeq(int size);
~PilhaSeq();
// Mtodos principais
void empilha(const Tipo &elem) throw (logic_error);
Tipo desempilha() throw (logic_error);
// Mtodos auxiliares
bool cheia();
bool vazia();
int tamanho();
private:
Tipo *vetor;
int topo, size;
};
P
i
l
h
a
S
e
q
.
h
26
Implementaes
Pilha sequencial
// Construtor
template <typename Tipo>
PilhaSeq<Tipo>::PilhaSeq(int size) {
this->size = size;
vetor = new Tipo[size];
topo = -1;
}
P
i
l
h
a
S
e
q
.
h
27
Implementaes
Pilha sequencial
// Destrutor
template <typename Tipo>
PilhaSeq<Tipo>::~PilhaSeq() {
delete [] vetor;
}
P
i
l
h
a
S
e
q
.
h
28
Implementaes
Pilha sequencial
// Empilha
template <typename Tipo>
void PilhaSeq<Tipo>::empilha(const Tipo &el) throw (logic_error){
if (topo == (size-1))
throw logic_error("Pilha cheia");
vetor[++topo] = el;
}
P
i
l
h
a
S
e
q
.
h
29
Implementaes
Pilha sequencial
// Desempilha
template <typename Tipo>
Tipo PilhaSeq<Tipo>::desempilha() throw (logic_error) {
if (topo < 0)
throw logic_error("Pilha vazia");
return(vetor[topo--]);
}
P
i
l
h
a
S
e
q
.
h
30
Implementaes
Pilha sequencial
// Mtodos auxiliares
template <typename Tipo>
bool PilhaSeq<Tipo>::cheia() {
return(topo == (size-1));
}
template <typename Tipo>
bool PilhaSeq<Tipo>::vazia() {
return(topo <0);
}
template <typename Tipo>
int PilhaSeq<Tipo>::tamanho() {
return(topo + 1);
}
P
i
l
h
a
S
e
q
.
h
31
Demais informaes
Pilha sequencial
#ifndef _PilhaSeq_H
#define _PilhaSeq_H
#include <stdexcept.h>
using std::logic_error;
namespace ED {
template <typename Tipo>
class PilhaSeq { ...
};
// Implementaes
}
#endif
P
i
l
h
a
S
e
q
.
h
Inclusion Guards
Biblioteca para excees
Para utilizar a classe logic_error
Para organizao
32
Exemplo de utilizao da nossa PilhaSeq
Pilha sequencial
#include <iostream>
#include PilhaSeq.h
using ED::PilhaSeq;
int main(int argc, char** argv) {
PilhaSeq<int> p(30);
for (int i=0; i<20; i++)
p.empilha(i);
for (int i=0; i<20; i++)
cout << p.desempilha() << endl;
}
M
a
i
n
.
c
p
p
33
Exemplo de utilizao da nossa PilhaSeq
Pilha sequencial
#include <iostream>
#include PilhaSeq.h
using ED::PilhaSeq;
int main(int argc, char** argv) {
PilhaSeq<int> p(30);
for (int i=0; i<20; i++)
p.empilha(i);
for (int i=0; i<20; i++)
cout << p.desempilha() << endl;
}
M
a
i
n
.
c
p
p
Aqui, o utilizador no est
interessado em receber
mensagens da pilha.
Tudo bem, ele no
obrigado, mas se ele quiser,
ele pode: try...catch
34
Recebendo mensagens da pilha com try... catch
Pilha sequencial
#include <iostream>
#include PilhaSeq.h
using ED::PilhaSeq;
int main(int argc, char** argv) {
PilhaSeq<int> p(30);
try {
for (int i=0; i<20; i++) p.empilha(i);
for (int i=0; i<20; i++)
cout << p.desempilha() << endl;
}
catch (logic_error err){
cout << err.what();
}
}
M
a
i
n
.
c
p
p
35
Exemplo de uma pilha de pontos (x,y)
Pilha sequencial
36
Exemplo de uma pilha de pontos (x,y)
#include <iostream>
#include PilhaSeq.h
using ED::PilhaSeq;
struct Ponto2D {
int x, y;
};
int main(int argc, char** argv) {
PilhaSeq<Ponto2D> p(50);
Ponto2D pt;
for (int i=0; i<5; i++)
for (int j=0; j<5; j++) {
pt.x = i;
pt.y = j;
p.empilha(pt);
}
for (int i=0; i<25; i++) {
pt = p.desempilha();
cout << pt.x << , << pt.y << endl;
}
}
M
a
i
n
.
c
p
p
37
Perguntas sobre o exemplo anterior
Onde est alocada a varivel pt ?
Onde est alocado o objeto p?
Onde est alocada a memria sequencial para a pilha do objeto p?
Quantos bytes utilizado na memria sequencial para a pilha do objeto p?
O que acontece se fizermos
Ponto2D p1, p2;
p1.x=10;
p2 = p1;
No lugar de estruct poderamos ter uma classe?
Pilha sequencial
38
Qual a maior desvantagem da pilha sequencial?
Pilha sequencial
39
Qual a maior desvantagem da pilha sequencial?
Ela tem um tamanho fixo que, definido na sua
criao
Se a pilha est com poucos elementos, muita memria
estar sendo alocada desnecessariamente
Se a pilha est quase cheia, ento, provavelmente, ela ir
encher em breve, e no poderemos mais inserir elementos
Pilha sequencial
40
Podemos dar um bom palpite sobre o tamanho
inicial da ED, mas sempre estaremos entre um ou
outro caso:
Memria sub utilizada
Falta de espao
Pilha sequencial
41
Por isso, podemos utilizar uma tcnica clssica de
implementao de EDs lineares: o encadeamento;
No encadeamento, utilizamos ns, ou, clulas, para
armazenar a informao. Ento, por meio de
ponteiros, mantemos um encadeamento das clulas.
Pilha encadeada
42
Exemplo de pilha encadeada:
Pilha encadeada
topo
43
Pelo fato de a ED ter agora um tamanho no fixo,
comum chamar a ED de pilha dinmica. Mas no
confunda esse nome dinmica, com o tipo de
alocao de memria. Vimos que a fila sequencial
tambm utiliza alocao dinmica de memria,
embora com um tamanho fixo, pr-estabelecido.
Pilha encadeada
topo
44
O n da ED encadeada pode ser uma struct ou uma
classe. O importante que ela tenha uma parte de
dados e um ponteiro para outra clula do mesmo
tipo
Pilha encadeada
class Celula
public:
Tipo el;
Celula *prox;
};
struct Celula
Tipo el;
Celula *prox;
};
ou
Celula *prox;
Tipo el;
45
Estado inicial da pilha
Pilha encadeada
topo
46
Empilhando um elemento: 10
Pilha encadeada
topo
Celula *nova = new Celula;
nova
47
Empilhando um elemento: 10
Pilha encadeada
topo
10
nova
48
Celula *nova = new Celula;
nova->el = 10;
Empilhando um elemento: 10
Pilha encadeada
topo
10
nova
49
Celula *nova = new Celula;
nova->el = 10;
nova->prox = topo;
Empilhando um elemento: 10
Pilha encadeada
topo
10
nova
50
Celula *nova = new Celula;
nova->el = 10;
nova->prox = topo;
topo = nova;
nelem++;
Empilhando um elemento: 20
Pilha encadeada
10
nova
topo
20
51
Celula *nova = new Celula;
nova->el = 20;
nova->prox = topo;
topo = nova;
nelem++;
Desempilhando
Pilha encadeada
Tipo ret = topo->el;
10
topo
20 ret
20
52
Desempilhando
Pilha encadeada
Tipo ret = topo->el;
Celula *aux = topo;
10
topo
20
aux
20
53
ret
Desempilhando
Pilha encadeada
Tipo ret = topo->el;
Celula *aux = topo;
topo = topo->prox;
10
topo
20
aux
20
54
ret
Desempilhando
Pilha encadeada
Tipo ret = topo->el;
Celula *aux = topo;
topo = topo->prox;
delete aux;
nelem--;
return(ret);
10
topo
20
55
ret
Desempilhando
Pilha encadeada
Tipo ret = topo->el;
Celula *aux = topo;
topo = topo->prox;
delete aux;
nelem--;
return(ret);
topo
10
56
ret
Classe PilhaEnc em C++.
Pilha encadeada
template <typename Tipo>
class PilhaEnc {
public:
PilhaEnc();
~PilhaEnc();
// Mtodos principais
void empilha(const Tipo &elem) throw (logic_error);
Tipo desempilha() throw (logic_error);
// Mtodos auxiliares
bool vazia();
int tamanho();
private:
struct Celula {
Tipo el;
Celula *prox;
};
Celula *topo;
int nelem;
};
P
i
l
h
a
E
n
c
.
h
57
Implementaes
Pilha encadeada
// Construtor
template <typename Tipo>
PilhaEnc<Tipo>::PilhaEnc() {
topo = NULL;
nelem = 0;
}
P
i
l
h
a
E
n
c
.
h
58
Implementaes
Pilha encadeada
// Destrutor
template <typename Tipo>
PilhaEnc<Tipo>::~PilhaEnc() {
Celula *aux;
while (topo) {
aux = topo;
topo = topo->prox;
delete aux;
}
}
P
i
l
h
a
E
n
c
.
h
59
Implementaes
Pilha encadeada
// Empilha
template <typename Tipo>
void PilhaEnc<Tipo>::empilha(const Tipo &el) throw (logic_error){
Celula *nova = new Celula;
if (nova == NULL) throw logic_error("Falta memoria\n");
nova->el = el; // Cria-se uma cpia do elemento el
nova->prox = topo;
topo = nova;
nelem++;
}
P
i
l
h
a
E
n
c
.
h
60
Implementaes
Pilha encadeada
// Desempilha
template <typename Tipo>
Tipo PilhaEnc<Tipo>::desempilha() throw (logic_error) {
if (nelem == 0) throw logic_error("Pilha vazia\n");
Tipo ret = topo->el;
Celula *aux = topo;
topo = topo->prox;
delete aux;
nelem--;
return(ret);
}
P
i
l
h
a
E
n
c
.
h
61
Implementaes
Pilha encadeada
// Mtodos auxiliares
template <typename Tipo>
bool PilhaEnc<Tipo>::vazia() {
return(nelem == 0);
}
template <typename Tipo>
int PilhaEnc<Tipo>::tamanho() {
return(nelem);
}
P
i
l
h
a
E
n
c
.
h
62
A pilha encadeada possui a vantagem de no ter um
tamanho fixo.
Alm disso, a pilha encadeada facilita o aproveitamento
de memria interna, pois mais fcil alocar muitos
blocos pequenos de memria do que um nico bloco
muito grande.
Porm, o encadeamento utiliza mais memria pois
precisa de memria para os ponteiros.
Pilha encadeada x sequencial
63
A pilha sequencial tende a realizar empilhamento e
desempilhamento mais rpido, pois no precisa
alocar e desalocar memria no momento dessas
operaes.
Em linha gerais, no podemos dizer que uma
melhor que a outra. Temos que levar em
considerao cada aplicao separadamente.
Pilha encadeada x sequencial
64
Nas implementaes apresentadas nestas aulas, os itens de
dados so armazenados dentro da memria alocada para a
pilha, seja ela sequencial ou encadeada.
Existe tambm a possibilidade de uma implementao onde
no so armazenados os dados em si, mas sim, ponteiros para
esses itens.
O grande problema desse tipo de implementao fica por
conta da desalocao de memria.
Pilha encadeada x sequencial
65
Implementar:
pilha sequencial
pilha encadeada
Utilizar os dois tipos de pilha para desenvolver as
seguintes aplicaes :
Exerccios
66
Exerccios
1 Implementar uma calculadora para expresses
aritmticas de notao ps-fixada
Exemplos
3*(4+5) <-> 3 4 5 + *
(3+4)*(7+8) <-> 3 4 + 7 8 + *
Algoritmo bsico
Leia um nmero ou um operador
Se for nmero, empilhe
Se for operador, desempilhe os ltimos 2 nmeros, realize a operao
correspondente e empilhe o resultado
67
Exerccios
2 Implementar a funo paint bucket
68
. . . . x
. . x x .
. . x . .
x x . . .
. . . . .
Entrada: uma matriz mxn
com x ou . em cada
elemento. Exemplo:
Um ponto semente. Ex (2, 3)
e
Sada: uma matriz
alterada. Exemplo:
. . . . x
. . x x x
. . x x x
x x x x x
x x x x x
Utilizar hard-coding
Exerccios
2 Implementar a funo paint bucket
Algoritmo bsico
empilhe o ponto inicial (x
i
, y
i
)
enquanto a pilha no estiver vazia
desempilha um ponto (x, y)
se (x,y) um ponto vlido e se no estiver pintado (x)
pinte (x, y) e empilhe os 4 vizinhos
69
Exerccios
3 Implementar um programa para validar uma
expresso aritmtica com relao ao balenceamento
de () [] e {}
Exemplo:
d^{[(a+b) *c] * [c*(a+d) ^(d+e)]} ok
d^{[(a+b) *c] * c*(a+d) ^(d+e)]} errado
70
Exerccios
3 Implementar um programa para validar uma
expresso aritmtica com relao ao balenceamento
de () [] e {}
Algoritmo
Ler um smbolo (letra, operador, um delimitador )
Se for um ( ou um [ ou um {
Empilha o smbolo
Se for um ) ou um ] ou um }
Desempilha um smbolo e compara com o smbolo de entrada
Se forem diferente, retorna errado
Se for igual, continua.
Ao trmino da cadeia, se a pilha estiver vazia, retorna correto
71

Potrebbero piacerti anche