Comentários

0%

FOCO NO MERCADO DE TRABALHO

Pilhas

Paulo Afonso Parreira Júnior

Utilização de Pilha para verificar a consistência do arquivo de configuração

Criação de um programa com a utilização de pilha, para verificar o arquivo com os dados de um jogador, quanto ao uso dos símbolos de agrupamentos, decidindo se eles estão corretos ou não.

Fonte: Shutterstock.

Deseja ouvir este material?

Áudio disponível no material digital.

Sem medo de errar

ROTEIRO PARA O PROFESSOR

Para auxiliar no desenvolvimento das competências e motivar a resolução da situação-problema, peça aos alunos que acessem e leiam o conteúdo da página “3.7 Símbolos Balanceados” (MILLER; RANUM, [s. d.]), disponível em: https://bit.ly/3opzNtT.

Nela, os alunos terão uma boa abordagem da relevância da situação-problema para o mundo a computação.

Ao final da leitura, como atividade, peça aos alunos que traduzam o código disponibilizado na página (apesar de estar escrito em Python, com a explicação do código na página, é possível compreender seu funcionamento) para pseudocódigo. O intuito é permitir uma melhor compreensão da solução proposta por parte dos alunos.

Você foi contratado por ume empresa desenvolvedora de jogos digitais para escrever um programa que verifica se o arquivo com os dados de um jogador está correto ou não, quanto ao uso dos símbolos de agrupamentos, tais como {, [, ], }. Uma pilha pode ser convenientemente utilizada para resolver esse problema. Um exemplo de algoritmo capaz de avaliar uma expressão com os símbolos de agrupamento (), {} e [] e retornar “true” se ela é válida e “false” se é inválida, é apresentado no Código 4.27 a seguir.

O algoritmo funciona da seguinte forma: lendo a expressão da esquerda para a direita (isso é feito por meio do laço for da função “valida”), toda vez que se encontra um símbolo de abertura, insere-se esse símbolo na pilha (linhas 15, 16 e 17) e toda vez que se encontra um símbolo de fechamento, retira-se o símbolo do topo da pilha e verifica se os dois são do mesmo tipo (linhas 18 a 22). Caso sim, continue com o processo. Se a pilha estiver vazia após ter sido processada toda a sequência, então a expressão está correta.

As possíveis situações de erro, que indicam que a expressão é inválida, são:

Código 4.27 | Algoritmo para verificação de dados de um jogador
bool combina(char c1, char c2) {
    switch(c1) {
        case ')': return c2 == '(';
        case '}': return c2 == '{';
        case ']': return c2 == '[';
        default: return false;
    }
}

bool validar(char exp[], int tam) {
        struct Pilha* p = criar();
        for (int i = 0; i < tam; i++) {    
            char c = exp[i];
            switch(c) {
                case '(':
                case '{':
                case '[': empilhar(p, c); break;
                case ')':
                case '}':
                case ']': {
                    if (vazia(p) == true) return false;
                    if (combina(c, desempilhar(p)) == false) return false;
                }                    
            }
        }
        return (vazia(p));
}


int main() {
    char exp[] = "{([])}";
    printf("Resultado (1 = Correta; 0 = Incorreta): %d\n", validar(exp, 6));

    return 0;
}
Fonte: elaborado pelo autor.

Avançando na prática

Clonar pilha

Implemente uma nova função para a ED pilha, denominada “clonar”. Essa função deve ser capaz de criar uma nova pilha, a partir de uma pilha já existente, clonando os elementos da pilha original para a nova pilha.

Uma possível solução para o problema é apresentada a seguir. A ideia do algoritmo é a seguinte: inicialmente, cria-se duas pilhas, “aux” e “clone” (linhas 3 e 4). A pilha “clone” vai conter os elementos da pilha original e serão retornados no final da função (linha 17). A pilha “aux” serve como auxiliar para que os elementos da pilha original não sejam perdidos no processo de clonagem. Além disso, a pilha “aux” tem outra utilidade: garantir que os elementos da pilha original e da pilha clonada estejam na ordem correta. Isso acontece porque se simplesmente copiarmos os elementos de uma pilha para a outra, os elementos da pilha em que os elementos foram copiados estarão na ordem inversa. Após transferir todos os elementos da pilha passada por parâmetro para a pilha auxiliar (linhas 6 a 8), deve-se voltar os elementos para a pilha original “p” e para a pilha “clone”, conforme pode ser visto nas linhas 10 a 14. Por fim, não se deve esquecer de liberar a pilha “aux”, para que ela não fique ocupando espaço na memória do computador (lembre-se: toda memória alocada com a função “malloc” deve ser liberada pelo programador usando a função “free”).

Código 4.28 | Pilha Clone
struct Pilha* clonar(struct Pilha* p) {
    assert(p != NULL);
    struct Pilha* clone = criar();
    struct Pilha* aux = criar();
    
    while(vazia(p) == false) {
        empilhar(aux, desempilhar(p));
    }

    while(vazia(aux) == false) {
        int elemento = desempilhar(aux);
        empilhar(clone, elemento);
        empilhar(p, elemento);
    }

    liberar(aux);
    return clone;    
}
Fonte: elaborado pelo autor.
Bons estudos!

AVALIE ESTE MATERIAL

OBRIGADO PELO SEU FEEDBACK!