Anda di halaman 1dari 71

Ps-Graduao em Cincias da Computao

Anlise de Algoritmos e Estrutura de Dados

UFABC
Universidade Federal do ABC
Aula 04

Prof. Andr G. R. Balan


andre.balan@ufabc.edu.br

Contedo

Pilhas
Sequencial Encadeada Aplicaes

Introduo
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
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?
4

Introduo
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
Estruturas de

dados elementares (lineares)

Pilhas Filas Listas

Mtodos de implementao
Sequencial
Encadeado

Pilha sequencial (sequential stack)

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


7

Pilha sequencial

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

Vamos supor uma pilha sequencial de


inteiros
n-1

Inicialmente, alocamos um vetor como

desejarmos: alocao esttica (stack) ou


dinmica (heap)

. . . 1 0
9

Vamos preferir alocao dinmica

Pilha sequencial

Inicialmente a pilha est vazia


n-1

Precisamos de uma varivel ndice para


determinar o topo da pilha

. . . 1 0
10

Pilha sequencial

Inicialmente a pilha est vazia


n-1

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;
topo

. . . 1 0
11

Pilha sequencial

Vamos inserir o inteiro 20


n-1

. . . 1 0 topo
12

Pilha sequencial

Primeiro incrementamos de uma unidade o


topo: topo++
n-1

. . . 1 topo 0
13

Pilha sequencial

Primeiro incrementamos de uma unidade


o topo: topo++
n-1

Em seguida, inserimos o elemento 20,

onde topo est indicando

. . . 1 topo 20 0
14

Pilha sequencial

Agora vamos empilhar outros elementos


n-1

. . . 1 topo 20 0
15

Pilha sequencial

Agora vamos empilhar outros elementos


n-1

. . . topo 30 20 1 0
16

Pilha sequencial

Agora vamos empilhar outros elementos


n-1

topo

40 30 20

. . . 1 0
17

Pilha sequencial

Mas preciso ter cuidado: o vetor tem uma

quantidade limitada de memria


topo

100 90 80 70 60 50 40 30 20

n-1

Um nova insero requer sempre uma

verificao inicial:
topo == n-1 ?

. . . 1 0
18

Se sim, a pilha deve avisar o utilizar por meio de algum mecanismo que a pilha est cheia

Pilha sequencial

Mecanismos de comunicao ED/utilizador:


Mensagem direta: Valor de retorno: cout << Pilha cheia 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
19

Pilha sequencial

Agora vamos desempilhar alguns


elementos
topo 100 90 80 70 60 50 40 30 20 . . . 1 0
20

n-1

Pilha sequencial

Agora vamos desempilhar alguns


elementos

100

n-1

topo

90 80 70 60 50 40 30 20 . . . 1 0
21

Pilha sequencial

Agora vamos desempilhar alguns


elementos
90
n-1

topo

80 70 60 50 40 30 20 . . . 1 0
22

Pilha sequencial

Agora vamos desempilhar alguns


elementos
n-1

Tambm preciso tomar cuidado:


Se a pilha estiver vazia, uma tentativa de desempilhamento deve gerar um aviso ao utilizador: Pilha vazia
20 . . . 1 0 topo
23

Pilha sequencial

Agora, vamos criar uma classe PilhaSeq para inteiros, em C++


class PilhaSeq { public: PilhaSeq(int size); ~PilhaSeq();

PilhaSeq.h

// Mtodos principais void empilha(int elem); int desempilha(); // Mtodos auxiliares bool cheia(); bool vazia(); int tamanho(); private: int *vetor; int topo, size; };
24

Pilha sequencial

Acontece, que queremos um ED genrica. Vamos utilizar templates


template <typename Tipo> class PilhaSeq { public: PilhaSeq(int size); ~PilhaSeq();

PilhaSeq.h

// Mtodos principais void empilha(const Tipo &elem); Tipo desempilha(); // Mtodos auxiliares bool cheia(); bool vazia(); int tamanho(); private: Tipo *vetor; int topo, size; };
25

Pilha sequencial

Vamos convensionar que a ED utilizar excees para comunicao


template <typename Tipo> class PilhaSeq { public: PilhaSeq(int size); ~PilhaSeq();

PilhaSeq.h

// 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; };
26

Pilha sequencial

Implementaes

// Construtor template <typename Tipo> PilhaSeq<Tipo>::PilhaSeq(int size) { this->size = size; vetor = new Tipo[size]; topo = -1; }

PilhaSeq.h

27

Pilha sequencial

Implementaes

PilhaSeq.h

// Destrutor template <typename Tipo> PilhaSeq<Tipo>::~PilhaSeq() { delete [] vetor; }

28

Pilha sequencial

Implementaes

PilhaSeq.h

// 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; }

29

Pilha sequencial

Implementaes

PilhaSeq.h

// Desempilha template <typename Tipo> Tipo PilhaSeq<Tipo>::desempilha() throw (logic_error) { if (topo < 0) throw logic_error("Pilha vazia"); return(vetor[topo--]); }

30

Pilha sequencial

Implementaes
// Mtodos auxiliares template <typename Tipo> bool PilhaSeq<Tipo>::cheia() { return(topo == (size-1)); }

PilhaSeq.h

template <typename Tipo> bool PilhaSeq<Tipo>::vazia() { return(topo <0); } template <typename Tipo> int PilhaSeq<Tipo>::tamanho() { return(topo + 1); }

31

Pilha sequencial

Demais informaes
#ifndef _PilhaSeq_H #define _PilhaSeq_H #include <stdexcept.h>

Inclusion Guards Biblioteca para excees Para utilizar a classe logic_error Para organizao

PilhaSeq.h

using std::logic_error;
namespace ED {

template <typename Tipo> class PilhaSeq {... }; // Implementaes } #endif


32

Pilha sequencial

Exemplo de utilizao da nossa PilhaSeq

#include <iostream> #include PilhaSeq.h using ED::PilhaSeq;

Main.cpp

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;
}
33

Pilha sequencial

Exemplo de utilizao da nossa PilhaSeq

#include <iostream> #include PilhaSeq.h using ED::PilhaSeq;

Main.cpp

Aqui, o utilizador no est interessado em receber mensagens da pilha. Tudo bem, ele no obrigado, mas se ele quiser, ele pode: try...catch

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;
}
34

Pilha sequencial

Recebendo mensagens da pilha com try... catch


#include <iostream> #include PilhaSeq.h

using ED::PilhaSeq;

Main.cpp

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(); } }
35

Pilha sequencial

Exemplo de uma pilha de pontos (x,y)

36

#include <iostream> #include PilhaSeq.h

using ED::PilhaSeq; struct Ponto2D { int x, y; };

Exemplo de uma pilha de pontos (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; } }
37

Main.cpp

Pilha sequencial

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?

38

Pilha sequencial

Qual a maior desvantagem da pilha sequencial?

39

Pilha sequencial

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

40

Pilha sequencial

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

41

Pilha encadeada

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.

42

Pilha encadeada
Exemplo

de pilha encadeada:

topo

43

Pilha encadeada

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.


topo

44

Pilha encadeada

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
struct Celula Tipo el; Celula *prox; };

ou

class Celula public: Tipo el; Celula *prox; };

Tipo el;

Celula *prox;
45

Pilha encadeada

Estado inicial da pilha

topo

46

Pilha encadeada

Empilhando um elemento: 10

Celula *nova = new Celula;

topo

nova
47

Pilha encadeada

Empilhando um elemento: 10

Celula *nova = new Celula; nova->el = 10;

topo

10

nova
48

Pilha encadeada

Empilhando um elemento: 10

Celula *nova = new Celula; nova->el = 10; nova->prox = topo;

topo

10

nova
49

Pilha encadeada

Empilhando um elemento: 10

Celula *nova = new Celula; nova->el = 10; nova->prox = topo; topo = nova; nelem++;

topo 10

nova
50

Pilha encadeada

Empilhando um elemento: 20

Celula *nova = new Celula; nova->el = 20; nova->prox = topo; topo = nova; nelem++;

topo 20

10

nova
51

Pilha encadeada

Desempilhando

Tipo ret = topo->el;

topo 20

10

ret

20

52

Pilha encadeada

Desempilhando

Tipo ret = topo->el; Celula *aux = topo;

topo 20

10

aux

ret

20

53

Pilha encadeada

Desempilhando

Tipo ret = topo->el; Celula *aux = topo; topo = topo->prox;

topo

20

10

aux

ret

20

54

Pilha encadeada

Desempilhando

Tipo ret = topo->el; Celula *aux = topo; topo = topo->prox; delete aux; nelem--; return(ret);

topo

10

ret

20

55

Pilha encadeada

Desempilhando

Tipo ret = topo->el; Celula *aux = topo; topo = topo->prox; delete aux; nelem--; return(ret);

topo

ret

10

56

Pilha encadeada

Classe PilhaEnc em C++.


template <typename Tipo> class PilhaEnc { public: PilhaEnc(); ~PilhaEnc();
// Mtodos principais void empilha(const Tipo &elem) throw (logic_error); Tipo desempilha() throw (logic_error);

PilhaEnc.h

// Mtodos auxiliares bool vazia(); int tamanho(); private: struct Celula { Tipo el; Celula *prox; };
Celula *topo; int nelem; }; 57

Pilha encadeada

Implementaes

PilhaEnc.h

// Construtor template <typename Tipo> PilhaEnc<Tipo>::PilhaEnc() { topo = NULL; nelem = 0; }

58

Pilha encadeada

Implementaes

// Destrutor template <typename Tipo> PilhaEnc<Tipo>::~PilhaEnc() { Celula *aux; while (topo) { aux = topo; topo = topo->prox; delete aux; } }

PilhaEnc.h

59

Pilha encadeada

Implementaes

PilhaEnc.h

// 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; nova->prox = topo;

topo = nova; nelem++; }

60

Pilha encadeada

Implementaes

// Desempilha template <typename Tipo> Tipo PilhaEnc<Tipo>::desempilha() throw (logic_error) {

PilhaEnc.h

if (nelem == 0)

throw logic_error("Pilha vazia\n");

Tipo ret = topo->el; Celula *aux = topo; topo = topo->prox; delete aux; nelem--;
return(ret); }

61

Pilha encadeada

Implementaes

// Mtodos auxiliares
template <typename Tipo> bool PilhaEnc<Tipo>::vazia() { return(nelem == 0); }

PilhaEnc.h

template <typename Tipo> int PilhaEnc<Tipo>::tamanho() { return(nelem); }

62

Pilha encadeada x sequencial

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.
63

Pilha encadeada x sequencial

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.

64

Pilha encadeada x sequencial

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.
65

Exerccios
Implementar:

pilha sequencial
pilha encadeada

Utilizar os dois tipos de pilha para desenvolver as


seguintes aplicaes :

66

Exerccios

1 Implementar uma calculadora para expresses aritmticas de notao ps-fixada

Exemplos 3*(4+5) (3+4)*(7+8)


Algoritmo bsico

<-> 3 4 5 + * <-> 3 4 + 7 8 + *

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


Entrada: uma matriz mxn com x ou . em cada elemento. Exemplo:

Um ponto semente. Ex (2, 3)

. . . x .

. . . x .

. x x . .

. x . . .

x . . . .

Sada: uma matriz alterada. Exemplo:

Utilizar entrada e sada de arquivos texto

. . . x x

. . . x x

. x x x x

. x x x x

x x x x x
68

Exerccios

2 Implementar a funo paint bucket

Algoritmo bsico
empilhe o ponto inicial (xi, yi) 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)]} d^{[(a+b) *c] * c*(a+d) ^(d+e)]} ok 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

Anda mungkin juga menyukai