Você está na página 1de 7

Material de Pilha: Exemplos e Exercícios – Joisa

Pilha:

Estrutura de dados que é caracterizada pela sua estratégia (disciplina/política) de


inserção/retirada, que é a LIFO (Last In, First Out – Last In, First Out – o último a entrar é o
primeiro a sair).

A propriedade da pilha é, na SAÍDA, INVERTER a ordem de ENTRADA dos dados.

TAD: Pilha de inteiros.

Exemplo 1:

Considere a interface do TAD Pilha (de inteiros) definida abaixo, que deve estar no arquivo
pilha.h:

/* TAD Pilha de inteiros */


/* interface: arquivo pilha.h */

typedef struct pilha Pilha;

/* função que cria, inicializa e retorna o endereço de (o ponteiro para) uma


nova pilha de inteiros */
Pilha *piCria(void);

/* função que recebe um ponteiro para (o endereço de ) uma pilha de inteiros e um


novo elemento (no caso, um inteiro), fazendo a inserção desse elemento (sempre de
acordo com a estratégia de INS/RET em pilha) */
void piPush(Pilha *pi, int ninf);

/* função que recebe um ponteiro para (o endereço de ) uma pilha de inteiros e


faz a retirada de um elemento da pilha(no caso, um inteiro), retornando-o.
(Sempre de acordo com a estratégia de INS/RET em pilha) */
int piPop(Pilha *pi);

/* função que recebe um ponteiro para (o endereço de ) uma pilha de inteiros e


retorna 1, se a pilha é vazia, ou 0, caso contrário */
int piEhVazia(Pilha *pi);

/* função que recebe um ponteiro para (o endereço de ) uma pilha de inteiros e


libera o espaço ocupado pela pilha */
void piLibera(Pilha *pi);

Joisa – Pilha Page 1


1.A) Considerando a interface acima, escreva a função decEmBin, que recebe um número na
sua representação decimal e exibe na tela sua representação na base 2 (pensando naquele
algoritmo básico de sucessivas divisões por 2 e e obtenção dos restos).

Escreva essa função em um arquivo .c, contendo a função, os includes necessários e a main
com a chamada da função.

RESPOSTA:

/* arquivo principal.c: usuario do TAD Pilha de inteiros */

#include <stdio.h>
#include "pilha.h"

void decEmBin(int n);

int main (void)


{
decEmBin(13);

return 0;
}

void decEmBin(int n)
{ Pilha *piu;
int x, resto;

piu = piCria();
x = n;
while (x>0)
{ resto = x%2;
piPush(piu, resto);
x = x/2;
}
while (! piEhVazia(piu))
{ resto = piPop(piu);
printf("%d", resto);
}
piLibera(piu);
}

Joisa – Pilha Page 2


1.B.1) Escreva uma primeira implementação do TAD Pilha de inteiro usando um vetor de
inteiros e uma variável inteira n, que guarda o número de elementos na pilha. O nome do
arquivo deve ser pilha.c. Faça todos os includes necessários, defina a struct para a pilha
conforme a descrição anterior e implemente as funções publicadas no arquivo de interface
pilha.h.
RESPOSTA:
/* TAD Pilha de inteiros */
/* implementacao: arquivo Pilha.c */

#include <stdlib.h>
#include <stdio.h>
#include "pilha.h"
#define MAXEL 50

struct pilha
{ int elem[MAXEL]; /* int porque e´ pilha de inteiros */
int n; /* número de elementos na pilha */
};
Pilha *piCria(void)
{ Pilha *pi;
pi = (Pilha *) malloc (sizeof (Pilha));
if (pi == NULL)
{ printf("\nNao conseguiu criar a pilha\n");
exit(1);
}
pi->n = 0;
return pi;
}

void piPush(Pilha *pi, int ninf)


{ if(pi->n == MAXEL)
{ printf ("\nNao ha´ mais espaco da pilha\n");
return;
}
pi->elem[pi->n] = ninf; /* primeira posicao livre no vetor */
pi->n ++;
}

int piEhVazia(Pilha *pi)


{ if (pi->n == 0)
return 1; /* VAZIA !!! */
else
return 0; /* NAO VAZIA */
}

int piPop(Pilha *pi)


{ int sai; /* sai e´ do tipo do elemento da pilha */
if (pi->n == 0)
{ printf ("\nERRO: tentativa de retirada em pilha vazia\n");
exit(1);
}
sai = pi->elem[pi->n -1];
pi->n--;
return sai;
}

void piLibera(Pilha *pi)


{ free(pi);
}

Joisa – Pilha Page 3


1.B.2) Escreva uma segunda implementação do TAD Pilha de inteiro usando uma lista
encadeada, onde cada nó guarda o valor de um elemento da pilha.

Deve-se primeiro definir um tipo estruturado (uma struct) que represente o nó encadeado da
LSE. Depois deve ser definida a a struct que representa a pilha, que, nesse caso, deverá conter
apenas um ponteiro para nó encadeado (no momento da criação da pilha, esse ponteiro deve
ser inicializado com NULL). Esse ponteiro deverá apontar o nó que está no TOPO da pilha, ou
seja, o elemento mais recentemente inserido. Na inserção (push) de um novo elemento deve
ser criado um novo nó encadeado com alocação dinâmica (malloc). A informação sendo
inserida na pilha deve ser colocada no novo nó. O novo nó deve ficar apontando o nó que era
o “topo velho” e o topo da pilha deve apontar o novo nó.

O nome do arquivo deve ser pilha.c. Faça todos os includes necessários, defina a struct para a
pilha conforme a descrição anterior e implemente as funções publicadas no arquivo de
interface pilha.h.

RESPOSTA:

/* TAD Pilha de inteiros */


/* implementacao: arquivo pilha.c */
/* USANDO LISTA ENCADEADA */

#include <stdlib.h>
#include <stdio.h>
#include "Pilha.h"

/* definir uma struct que represente o no´encadeado */

typedef struct noEnc NoEnc;


struct noEnc
{ int info;
NoEnc *prox;
};

/* AQUI: struct que representa a PILHA */


struct pilha
{ NoEnc *topo; /* indica o elemento mais recentemente inserido */
};

Pilha *piCria(void)
{ Pilha *pi;
pi = (Pilha *) malloc (sizeof (Pilha));
if (pi == NULL)
{ printf("\nNao conseguiu criar a pilha\n");
exit(1);
}
pi->topo = NULL;
return pi;
}

Joisa – Pilha Page 4


void piPush(Pilha *pi, int ninf)
{ NoEnc *pnovo;
pnovo = (NoEnc *) malloc (sizeof (NoEnc));
if (pnovo == NULL)
{ exit(1);
}
pnovo->info = ninf;
pnovo->prox = pi->topo;
pi->topo = pnovo;
}

int piEhVazia(Pilha *pi)


{ if (pi->topo == NULL)
return 1; /* VAZIA !!! */
else
return 0; /* NAO VAZIA */
}

int piPop(Pilha *pi)


{ int sai; /* sai e´ do tipo do elemento da pilha */
NoEnc *paux;

if (pi->topo == NULL)
{ printf ("\nERRO: tentativa de retirada em pilha vazia\n");
exit(1);
}
paux = pi->topo;
pi->topo = paux->prox;
sai = paux ->info;
free (paux);
return (sai);
}

void piLibera(Pilha *pi)


{ NoEnc *paux;
/* primeiro liberar eventuais nos da lista encadeada */
while (pi->topo != NULL)
{ paux = pi->topo;
pi->topo = paux->prox;
free(paux);
}
/* agora liberar a pilha */
free(pi);
}

Joisa – Pilha Page 5


EXERCÍCIOS A SEREM FEITOS POR VOCÊ:

Ex1) Considere a interface do TAD PilhaCarac (Pilha de caracteres) definida abaixo, que deve
estar no arquivo PilhaCarac.h:

/* TAD PilhaCarac – pilha de caracteres */

/* interface: arquivo PilhaCarac.h */

typedef struct pilha PilhaCarac;

/* função que cria, inicializa e retorna o endereço de (o ponteiro para) uma


nova pilha de caracteres */
PilhaCarac *piCria(void);

/* função que recebe um ponteiro para (o endereço de ) uma pilha de caracteres e


um novo elemento (no caso, um caractere), fazendo a inserção desse elemento
(sempre de acordo com a estratégia de INS/RET em pilha) */
void piPush(PilhaCarac *pi, char ninf);

/* função que recebe um ponteiro para (o endereço de ) uma pilha de caracteres e


faz a retirada de um elemento da pilha(no caso, um caractere), retornando-o.
(Sempre de acordo com a estratégia de INS/RET em pilha) */
char piPop(PilhaCarac *pi);

/* função que recebe um ponteiro para (o endereço de ) uma pilha de caracteres e


retorna 1, se a pilha é vazia, ou 0, caso contrário */
int piEhVazia(PilhaCarac *pi);

/* função que recebe um ponteiro para (o endereço de ) uma pilha de caracteres e


libera o espaço ocupado pela pilha */
void piLibera(PilhaCarac *pi);

Considere que uma mensagem é codificada invertendo-se as sequências de não vogais.

Exemplos:

ESTRUTURAS_DE_DADOS codificada fica: ERTSUTURAD_SED_ADOS

PROVA codificada fica: RPOVA

Exercício 1.A:

Considerando a interface acima, escreva a função decodifica, que recebe uma cadeia contendo
uma mensagem codificada e apresenta na tela a mensagem original. Para isso a sua função
deve usar uma pilha de caracteres.

Escreva essa função em um arquivo .c, contendo a função, os includes necessários e a main
com a chamada da função.

Joisa – Pilha Page 6


Obs: Considere a mensagem recebida toda em letras maiúsculas.

Dica: Vá processando caractere a caractere. Se o caractere for uma não vogal, emplhe-o. Se for
uma vogal, desempilhe e vá exibindo os caracteres da pilha, até esvaziá-la, para depois mostrar
essa vogal. Não esqueça que os últimos caracteres podem ser não vogais também.

Exercício 1.2:

Escreva uma implementação do TAD PilhaCarac (pilha de caracteres) usando uma lista
encadeada, onde cada nó guarda o valor de um elemento da pilha.

Deve-se primeiro definir um nó encadeado para o nó da LSE, para depois definir-se a struct
que representa a pilha, que, nesse caso, deverá conter apenas um ponteiro para nó encadeado
(no momento da criação da pilha, esse ponteiro deve ser inicializado com NULL). Esse
ponteiro deverá apontar o nó que está no TOPO da pilha, ou seja, o elemento mais
recentemente inserido. Uma implementação apropriada cria na inserção (push) de um novo
elemento um novo nó encadeado com malloc. O novo nó deve ser preenchido com a
informação sendo inserida na pilha. O novo nó aponta o topo “velho” e o topo da pilha deve
apontar o novo nó.

O nome do arquivo deve ser PilhaCarac.c. Faça todos os includes necessários, defina a struct
para a pilha conforme a descrição anterior e implemente as funções publicadas no arquivo de
interface PilhaCarac.h.

Joisa – Pilha Page 7