Agora que já aprendemos como funciona a estrutura de dados dinâmica pilha e fizemos uma implementação em C, vamos aprender uma segunda versão para implementar uma estrutura de dados dinâmica do tipo pilha que pode ser um pouco mais fácil de entender.
Para a implementação que finalizamos na aula anterior nós criamos apenas uma estrutura para nossa pilha, a estrutura Nó. Assim, nossa pilha é uma sequência de nós encadeados. Ao implementar dessa forma, precisamos usar ponteiro para ponteiro ao desempilhar um elemento para conseguir alterar o topo da pilha na função main.
Agora vamos criar uma outra estrutura chamada Pilha, esta estrutura terá em seu interior um ponteiro para um Nó chamado topo. Ao utilizar esta abordagem, perceba que o topo da nossa pilha agora estará dentro da estrutura Pilha. Assim, basta passarmos o ponteiro para nossa Pilha e teremos acesso ao topo para realizar qualquer operação.
// estrutura Pilha typedef struct{ No *topo; int tam; }Pilha;
Como agora também temos uma estrutura chamada Pilha, vamos desenvolver um procedimento para inicializar corretamente nossa estrutura. Lembre-se que inicialmente toda pilha está vazia, então precisamos dizer que o topo é nulo e o tamanho é zero, assim:
// procedimento para inicializar uma variável do tipo Pilha void criar_pilha(Pilha *p){ p->topo = NULL; p->tam = 0; }
Com a estrutura Pilha, não precisamos mais retornar o novo Nó a ser empilhado. Assim, nossa função empilhar vira um procedimento recebendo como parâmetro nossa estrutura Pilha.
void empilhar(Pilha *p){ No *novo = malloc(sizeof(No)); if(novo){ novo->p = ler_pessoa(); novo->proximo = p->topo; // novo nó aponta para o topo atual p->topo = novo; // o topo passa a ser o novo nó p->tam++; } else printf("\nErro ao alocar memoria...\n"); }
O processo para desempilhar continua sendo uma função, pois retornamos o Nó desempilhado. Contudo, agora recebemos o ponteiro para nossa Pilha e não mais um ponteiro para ponteiro, pois o topo a ser alterado agora está dentro da estrutura Pilha.
No* desempilhar(Pilha *p){ if(p->topo){ No *remover = p->topo; // remover aponta para o topo p->topo = remover->proximo; // o topo passa a ser o próximo de remover p->tam--; return remover; } else printf("\nPilha vazia!\n"); return NULL; }
Por fim, também precisamos alterar a função main. Agora nossa variável para a pilha não será mais do tipo Nó, mas do tipo Pilha. Em seguida, precisamos inicializar corretamente nossa pilha com o procedimento criar_pilha, para só depois começar a realizar inserções e remoções na Pilha.
Código completo em C para a nova versão da estrutura de dados do tipo Pilha
/* Aula 224: Estrutura de dados PILHA: Segunda versão Código escrito por Wagner Gaspar Julho de 2021 */ typedef struct{ int dia, mes, ano; }Data; typedef struct{ char nome[50]; Data data; }Pessoa; typedef struct no{ Pessoa p; struct no *proximo; }No; typedef struct{ No *topo; int tam; }Pilha; Pessoa ler_pessoa(){ Pessoa p; printf("\nDigite nome e data de nascimento dd mm aaaa:\n"); scanf("%49[^\n]%d%d%d", p.nome, &p.data.dia, &p.data.mes, &p.data.ano); return p; } void imprimir_pessoa(Pessoa p){ printf("\nNome: %s\nData: %2d/%2d/%4d\n", p.nome, p.data.dia, p.data.mes, p.data.ano); } void criar_pilha(Pilha *p){ p->topo = NULL; p->tam = 0; } void empilhar(Pilha *p){ No *novo = malloc(sizeof(No)); if(novo){ novo->p = ler_pessoa(); novo->proximo = p->topo; p->topo = novo; p->tam++; } else printf("\nErro ao alocar memoria...\n"); } No* desempilhar(Pilha *p){ if(p->topo){ No *remover = p->topo; p->topo = remover->proximo; p->tam--; return remover; } else printf("\nPilha vazia!\n"); return NULL; } void imprimir_pilha(Pilha *p){ No *aux = p->topo; printf("\n----------- PILHA Tam: %d --------------\n", p->tam); while(aux){ imprimir_pessoa(aux->p); aux = aux->proximo; } printf("\n--------- FIM PILHA ------------\n"); } int main(){ No *remover; Pilha p; int opcao; criar_pilha(&p); do{ printf("\n0 - Sair\n1 - Empilhar\n2 - Desempilhar\n3 - Imprimir\n"); scanf("%d", &opcao); getchar(); switch(opcao){ case 1: empilhar(&p); break; case 2: remover = desempilhar(&p); if(remover){ printf("\nElemento removido com sucesso!\n"); imprimir_pessoa(remover->p); free(remover); } else printf("\nSem no a remover.\n"); break; case 3: imprimir_pilha(&p); break; default: if(opcao != 0) printf("\nOpcao invalida!!!\n"); } }while(opcao != 0); return 0; }