A B C D FE

12 

Full text

(1)

Pilha Estática

Uma pilha é um conjunto ordenado de itens no qual novos itens podem ser inseridos e a

partir do qual podem ser eliminados itens em uma extremidade chamada topo da pilha.

Podemos ilustrar uma pilha como a Figura 1. (PLT, pág86).

Ao contrário do que acontece com o vetor, a definição da pilha compreende a inserção e

a eliminação de itens, de modo que uma pilha é um objeto dinâmico, constantemente

mutável. Por conseguinte, surge então a pergunta: como uma pilha muda? A definição

especifica que uma única extremidade da pilha é designada como o topo da pilha.

Novos itens podem ser colocados no topo da pilha (em cujo caso este topo será

deslocado para cima, de modo a corresponder ao novo primeiro elemento), ou os itens

que estiverem no topo da pilha poderão ser removidos (em cujo caso esse topo será

deslocado para baixo, de modo a corresponder ao novo primeiro elemento). Para

responder à pergunta qual é o lado de cima?, precisamos determinar que extremidade da

pilha será designada como topo, isto é, em que extremidade serão incluídos ou

eliminados itens.

Desenhando a Figura 1 de modo que

F

esteja fisicamente em cima na página em relação

aos outros itens na pilha, estaremos implicando que

F

é o atual elemento superior da

pilha. Se forem incluídos novos itens na pilha, eles serão colocados acima de F e, se

forem eliminados alguns itens,

F

será o primeiro a ser eliminado. Isso é também

indicado pelas linhas verticais que se estendem além dos itens da pilha, na direção do

topo da pilha. (PLT, pág87).

Figura 1. Uma pilha contendo letras

A Figura 2 é um filme de uma pilha conforme ela se expande e se reduz com o passar

do tempo. A Figura 2a mostra o instantâneo da pilha da Figura 1. Na Figura 2b, o item

G

é incluído na pilha. De acordo com a definição, só existem um local na pilha onde ele

pode ser incluído – no topo. Agora, o primeiro elemento da pilha é

G

. Com a

movimentação da imagem pelos quadros

c

,

d

e

e

, os itens

H

,

I

e

J

são sucessivamente

incluídos na pilha. Entretanto, a partir do quadro

f

, a pilha começa a diminuir, quando

primeiro

J

, depois

I

,

H

e

G

são sucessivamente removidos. Em cada etapa, o elemento

superior é removido, uma vez que uma eliminação só pode ser feita a partir do topo. O

item

G

não poderia ser removido da pilha antes dos itens

J

,

I

e

H

. Isso ilustra o atributo

A

B

C

D

F

(2)

mais importante de uma pilha, em que o último elemento inserido numa pilha é o

primeiro elemento eliminado. Sendo assim,

J

é eliminado antes de

I

porque

J

foi

inserido depois de

I

. Por essa razão, ocasionalmente uma pilha é chamada lista last-in,

first-out (LIFO ou UEPS, o último a entrar é o primeiro a sair). (PLT, pág87)

Entre os quadros

j

e

k

, a pilha parou de diminuir e começou a crescer novamente, com a

inclusão do item

K

. Entretanto, esse crescimento tem vida curta, porque a pilha se reduz

a apenas três itens no quadro

n

.

Observe que não há como distinguir entre o quadro

a

e o quadro

i

, examinando o estado

da pilha nas duas ocorrências. Em ambos os casos, a pilha contém os mesmos itens, na

mesma ordem, e apresenta o mesmo topo. Não existe um registro do fato de que quatro

itens tenham sido incluídos e eliminados na pilha, nesse ínterim. De modo semelhante,

não há como distinguir entre os quadros

d

e

f

, ou

j

e

l

. Se for necessário um registro dos

itens intermediários que passaram pela pilha, esse registro deverá ser mantido em outro

lugar; ele não existe dentro da própria pilha.

Na realidade, apresentamos uma visão estendida do que é realmente observado numa

pilha. A verdadeira imagem de uma pilha é dada por uma visualização de cima para

baixo, em vez de por uma visão em perfil, de fora para dentro. Sendo assim, na Figura

2, não existe uma diferença perceptível entre os quadros

h

e

o

. Em cada caso, o

elemento posicionado no topo é

G

. Embora a pilha no quadro

h

e a pilha no quadro o

não sejam iguais, a única maneira de determinar esse fato é removendo todos os

elementos das duas pilhas e comparando-os individualmente. Mesmo que tenhamos

observado perfis laterais de pilhas para simplificar nosso entendimento, deve-se

observar que o fizemos arbitrariamente e que não há uma possibilidade real de existir tal

imagem. (PLT, pág88)

A

B

C

D

E

F

topo

A

B

C

D

E

F

G

A

B

C

D

E

F

G

A

B

C

D

E

F

G

A

B

C

D

E

F

G

H

A

B

C

D

E

F

G

H

A

B

C

D

E

F

G

H

I

A

B

C

D

E

F

G

H

I

J

H

I

(3)

Figura 2. Um Filme de uma pilha (PLT, pág89)

Operações Primitivas

As duas mudanças que podem ser introduzidas numa pilha recebem nomes especiais.

Quando um item é incluído numa pilha, ele é

empilhado

sobre a pilha e, quando um

item é removido, ele é

desempilhado

. Em função de uma pilha

s

e um item

i,

executar a

operação

push(s, i)

incluirá o item

i

no topo da pilha

s

. De modo semelhante, a operação

pop(s)

removerá o elemento superior e o retornará como valor da função. Assim a

operação de atribuição (PLT, pág88):

i = pop(s);

remove o elemento posicionado no topo de

s

e atribui seu valor a

i

.

Por exemplo, se s for a pilha da Figura 2, executaremos a operação push(s, G), ao passar

do quadro a para o b. Em seguida, executamos sucessivamente as seguintes operações:

push (s, H); quadro(c)

push (s, I); quadro(d)

push (s, J); quadro(e)

pop(s); quadro(f);

pop(s); quadro(g);

pop(s); quadro(h);

pop(s); quadro(i);

pop(s); quadro(j);

push (s,K); quadro(k);

pop(s); quadro(l);

A

B

C

D

E

F

A

B

C

D

E

A

B

C

D

A

B

C

A

B

C

G

(i)

A

B

C

D

E

(j)

A

B

C

D

E

K

(4)

pop(s); quadro(m);

pop(s); quadro(n);

push(s, G); quadro(o);

Devido à operação push que adiciona elementos a uma pilha, uma pilha é as vezes lista

pushdown.

Não existe um limite máximo para o número de itens que podem ser mantidos numa

pilha porque a definição não especifica quantos itens são permitidos no conjunto.

Empilhar outro item numa pilha simplesmente produz um conjunto maior de itens.

Entretanto, se uma pilha contiver um só item e ele for desempilhado, a pilha resultante

não conterá itens e será chamada

pilha vazia.

Embora a operação

push

seja aplicável a

qualquer pilha, a operação pop não pode ser aplicada à pilha vazia porque essa pilha não

tem elementos para desempilhar. Portanto, antes de aplicar o operador pop a uma pilha,

precisamos verificar se ela não está vazia (PLT, pág90).

Representando Pilhas em C

Uma pilha é um conjunto ordenado de itens, e C já contém um tipo de dado que

representa um conjunto ordenado de itens: o vetor. Portanto, sempre que a solução de

um problema exigir o uso de uma pilha, é tentador iniciar um programa declarando uma

variável pilha como um vetor. Contudo, uma pilha e um vetor são duas entidades

totalmente diferentes. O número de elementos num vetor é fixado e atribuído pela

declaração feita para o vetor. Em termos gerais, o usuário não pode alterar esse número.

Por outro lado, uma pilha é fundamentalmente um objeto dinâmico cujo tamanho está

sempre mudando à medida que os itens são desempilhados e empilhados (PLT, pág98).

Entretanto, mesmo que um vetor não seja uma pilha, ele pode ser a casa de uma pilha.

Ou seja, um vetor pode ser declarado suficientemente grande para armazenar o tamanho

máximo da pilha. Durante a execução do programa, a pilha pode aumentar e diminuir

dentro do espaço reservado para ela. Uma extremidade do vetor é o final fixo da pilha,

enquanto o topo da pilha se desloca constantemente, com a eliminação e a inclusão de

itens. Dessa forma, é necessário outro campo que, em cada ponto da execução do

programa, rastreie a atual posição do topo da pilha.

Implementação de uma Pilha de Números Inteiros

O programa a seguir, implementa uma pilha de números inteiros, implementando as

operações

push()

,

pop()

,

imprime_pilha1()

,

imprime_pilha2()

e

busca().

A operação

push

insere elementos no topo da pilha, a função

pop

remove o elemento do topo, a

função

imprime_pilha1()

imprime os elementos da base até o topo da pilha, a função

imprime_pilha2()

imprime os elementos do topo até a base da pilha e a função busca,

procura os elementos na pilha.

#include <stdio.h> #include <conio.h> #include <stdlib.h> #define MAX 5

(5)

int valor[MAX]; int topo;

int inicio; }; struct pilha p;

void push() {

int x;

if(p.topo == MAX) {

printf("\nPilha cheia!"); exit(1);

} else {

printf("\nDigite uma valor: "); scanf("%i",&x);

p.valor[p.topo] = x; p.topo++;

printf("Elemento %i inserido com sucesso!",x); }

getch(); }

void pop() {

if(p.topo == 0) {

printf("\nPilha Vazia!"); exit(1);

} p.topo--;

printf("Elemento %i removido com sucesso!",p.valor[p.topo]); getche();

}

void imprime_pilha1() {

int v; int i; i = p.inicio; while(i != p.topo) {

v = p.valor[i];

printf("\nElemento %i da pilha eh: %i",i,v); i++;

} getche(); }

void imprime_pilha2() {

int v; int i; i = p.topo-1; while(i != -1) {

v = p.valor[i];

(6)

} getche(); }

void busca() {

bool encontrou; int valor_procurado; int v;

int i; i = p.inicio;

printf("Entre com o valor que deseja buscar: "); scanf("%i",&valor_procurado);

while(i != p.topo) {

v = p.valor[i];

if(v == valor_procurado) {

printf("Elemento %i encontrado na posicao %i",p.valor[i],i); encontrou = 1;

} i++; }

if(encontrou != 1)

printf("Elemento %i nao encontrado",valor_procurado); getche();

}

main() {

p.inicio = p.topo = 0; int op;

while(op != 6) {

system("cls");

printf("Manipulacao de Pilha Estatica"); printf("\nDigite 1 para Insercao (PUSH)");

printf("\nDigite 2 para Imprimir a Pilha (BASE AO TOPO)"); printf("\nDigite 3 para Imprimir a Pilha (TOPO A BASE)"); printf("\nDigite 4 para Remover (POP)");

printf("\nDigite 5 para Buscar Elemento"); printf("\nDigite 6 para Sair");

printf("\nDigite a opcao desejada: "); scanf("%i",&op);

switch(op) {

case 1: push(); break; case 2: imprime_pilha1(); break; case 3: imprime_pilha2(); break; case 4: pop(); break; case 5: busca(); break; case 6: exit(1);

default: printf("\nEntre com uma opcao valida!"); }

(7)

Implementação de uma Pilha de Números Inteiros (com ponteiros)

A implementação abaixo, é a mesma apresentada anteriormente, com o uso de

ponteiros.

#include <stdio.h> #include <conio.h> #include <stdlib.h> #define MAX 5

struct pilha {

int valor[MAX]; int topo;

int inicio; };

void inicializaPilha(struct pilha *p) {

p->inicio = p->topo = 0; }

void push(struct pilha *p, int x) {

if(p->topo == MAX) {

printf("\nPilha cheia!"); exit(1);

} else {

p->valor[p->topo] = x; p->topo++;

printf("Elemento %i inserido com sucesso!",x); }

getch(); }

int pop(struct pilha *p) {

if(p->topo == 0) {

printf("\nPilha Vazia!"); exit(1);

}

p->topo--;

return p->valor[p->topo]; getche();

}

void imprime_pilha1(struct pilha *p) {

int v; int i;

i = p->inicio; while(i != p->topo) {

v = p->valor[i];

(8)

i++; } getche(); }

void imprime_pilha2(struct pilha *p) {

int v; int i;

i = p->topo-1; while(i != -1) {

v = p->valor[i];

printf("\nElemento %i da pilha eh: %i",i,v); i--;

} getche(); }

void busca(struct pilha *p) {

bool encontrou; int valor_procurado; int v;

int i;

i = p->inicio;

printf("Entre com o valor que deseja buscar: "); scanf("%i",&valor_procurado);

while(i != p->topo) {

v = p->valor[i];

if(v == valor_procurado) {

printf("Elemento %i encontrado na posicao %i",p->valor[i],i); encontrou = 1;

} i++; }

if(encontrou != 1)

printf("Elemento %i nao encontrado",valor_procurado); getche();

}

main() {

struct pilha p; inicializaPilha(&p); int op;

int x;

int num_recuperado; while(op != 6) {

system("cls");

printf("Manipulacao de Pilha Estatica"); printf("\nDigite 1 para Insercao (PUSH)");

printf("\nDigite 2 para Imprimir a Pilha (BASE AO TOPO)"); printf("\nDigite 3 para Imprimir a Pilha (TOPO A BASE)"); printf("\nDigite 4 para Remover (POP)");

(9)

printf("\nDigite 6 para Sair"); printf("\nDigite a opcao desejada: "); scanf("%i",&op);

switch(op) {

case 1:

printf("\nDigite uma valor: "); scanf("%i",&x);

push(&p, x); break;

case 2:

imprime_pilha1(&p); break;

case 3:

imprime_pilha2(&p); break;

case 4:

num_recuperado = pop(&p);

printf("\nElemento %i recuperado!",num_recuperado); getch();

break; case 5:

busca(&p); break;

case 6: exit(1); default:

printf("\nEntre com uma opcao valida!"); }

} }

Implementação de uma Pilha de Livros (com Ponteiros)

O programa abaixo implementa as funções push() e pop() para uma Pilha de Livros.

/* Pilha de Livros */

#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h>

#define MAX 5

struct no {

char nome[100]; };

struct pilha {

struct no nos[MAX]; int inicio;

int topo; int quantos; };

(10)

{

p->inicio = p->quantos = 0; p->topo = -1;

}

void push(struct pilha *p, char nome[30]) {

if(p->quantos == MAX) {

printf("\nPilha Cheia"); exit(1);

} else {

p->topo++; }

strcpy(p->nos[p->topo].nome, nome); p->quantos++;

printf("\n%s inserido com sucesso!",nome); getche();

}

void pop(struct pilha *p, char nome[30]) {

if(p->quantos == 0) {

printf("\nFila vazia"); exit(1);

} else {

strcpy(nome, p->nos[p->topo].nome); p->quantos--;

p->topo--; }

printf("\n%s removido com sucesso!"); getche();

}

main() {

struct pilha p; inicializaPilha(&p); char nome[100];

int op; while(op != 5) {

system("cls");

printf("Manipulacao de Pilha Estatica de Livros"); printf("\nDigite 1 para Insercao (PUSH)");

printf("\nDigite 2 para Remover (POP)"); printf("\nDigite 3 para Sair");

printf("\nDigite a opcao desejada: "); scanf("%i",&op);

getc(stdin);

(11)

case 1:

printf("Digite o nome de um livro: "); gets(nome);

push(&p,nome); break; case 2:

pop(&p, nome); break;

case 3: exit(1);

default: printf("\nEntre com uma opcao valida!"); }

} }

Implementação Pilha Tenembaum

#include <stdio.h> #include <conio.h> #include <stdlib.h>

#define STACKSIZE 100

struct stack {

int top;

int items[STACKSIZE]; };

void inicializaPilha(struct stack *ps) {

ps->top = -1; }

int empty(struct stack *ps) {

if(ps->top == -1) return (1); else

return (0); }

void push(struct stack *ps, int x) {

if(ps->top == STACKSIZE-1) {

printf("%s","Estouro e Pilha"); exit(1);

} else {

ps->items[++(ps->top)] = x; }

}

int pop(struct stack *ps) {

if(empty(ps)) {

(12)

exit(1); }

return (ps->items[ps->top--]); }

main() {

struct stack ps; inicializaPilha(&ps); int x;

int num_retorno; int op;

while(op != 3) {

system("cls");

printf("Manipulacao de Pilha Estatica Tenembaum"); printf("\nDigite 1 para Insercao (PUSH)");

printf("\nDigite 2 para Remover (POP)"); printf("\nDigite 3 para Sair");

printf("\nDigite a opcao desejada: "); scanf("%i",&op);

getc(stdin);

switch(op) {

case 1:

printf("Digite um valor inteiro: "); scanf("%i",&x);

push(&ps,x); break; case 2:

num_retorno = pop(&ps);

printf("O numero retornado eh %i",num_retorno); getch();

break; case 3: exit(1);

default: printf("\nEntre com uma opcao valida!"); }

Figure

Updating...

References

Updating...

Download now (12 pages)