Problema com Estrutura de Dados Pilha em C

1. Problema com Estrutura de Dados Pilha em C

joao pedro ache virgili
joaovirgili

(usa Ubuntu)

Enviado em 10/04/2016 - 14:24h

Olá, fiz um código de Pilha em c, mas não sei porque não está empilhando. Fiz pelo mesmo método um de lista encadeada e deu certo. Tenho tido certas dificuldades com estruturas de dados então fico sempre fazendo o mesmo código para fixar. Segue o código.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

struct pilha {
int valor;
struct pilha* prox;
};
typedef struct pilha Pilha;
Pilha topoPilha;
int tamPilha=0;

void Inicia (Pilha *topo);
void Insere (Pilha *topo, int num);
void Imprime (Pilha *topo);
bool Vazia (Pilha *topo);

int main (void) {
int i;
Inicia (&topoPilha);
Insere (&topoPilha, 3);
Insere (&topoPilha, 2);
Insere (&topoPilha, 1);
if (Vazia (&topoPilha))
printf("Pilha Vazia\n");
printf("%d\n", tamPilha);
Imprime (&topoPilha);
return 0;
}

void Inicia (Pilha *topo) {
topo = NULL;
}

void Insere (Pilha *topo, int num) {
Pilha *aux;
aux = malloc(sizeof(Pilha));
if (aux!=NULL) {
aux->valor = num;
aux->prox = topo;
topo = aux;
tamPilha++;
}
else
printf("Memoria não alocada");
}

bool Vazia (Pilha *topo) {
if (topo->prox == NULL)
return true;
else
return false;
}

void Imprime (Pilha *topo) {
while (topo->prox != NULL) {
printf("%d\n", topo->valor);
topo = topo->prox;
}
}


Quando rodo o programa, ele retorna:
Pilha Vazia
3

edit: tentei com este código também e está dando falha na segmentação.
 #include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

struct pilha {
int valor;
struct pilha* prox;
};
struct pilha *topoPilha;
int tamPilha=0;

void Inicia (struct pilha *topo);
void Insere (struct pilha *topo, int num);
void Imprime (struct pilha *topo);
bool Vazia (struct pilha *topo);

int main (void) {
Inicia(topoPilha);
Insere (topoPilha, 1);
Insere (topoPilha, 2);
Insere (topoPilha, 3);
Imprime(topoPilha);
//if (Vazia(topoPilha))
// printf("Pilha Vazia\n");
return 0;
}

void Inicia (struct pilha *topo) {
topo = NULL;
}

void Insere (struct pilha *topo, int num) {
struct pilha *aux = malloc(sizeof(struct pilha));
if (aux != NULL) {
aux->valor = num;
aux->prox = topo;
topo = aux;
printf("oi\n");
}
else
printf("Memoria nao alocada\n");
}

void Imprime (struct pilha *topo) {
//if (Vazia(topoPilha))
//printf("Pilha Vazia\n");
while (topo->prox != NULL) {
printf("%d\n", topo->valor);
topo = topo->prox;
}
}

bool Vazia (struct pilha *topo) {
if (topo->prox == NULL)
return true;
else
return false;
}






  


2. Re: Problema com Estrutura de Dados Pilha em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 10/04/2016 - 22:20h

joaovirgili escreveu:

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

struct pilha {
int valor;
struct pilha* prox;
};


Pense comigo: essa estrutura representa totalmente uma pilha, ou representa apenas um nó?

Como ela representa um nó, não acha que seria adequado mudar seu nome para indicar isso?

typedef struct pilha Pilha; 


Mesmo raciocínio a respeito do nome, mas com uma diferença: pode ser que lhe facilite a vida se você declarar o tipo como ponteiro para a estrutura. Por exemplo:

typedef struct no *ptr_no;

struct no {
int valor;
ptr_no prox;
};


Pilha topoPilha; 


Acho que você deveria ter um ponteiro para nó aqui, não um nó fixo. Por exemplo:

ptr_no topoPilha; 


Em todas as demais ocorrências do que você chamou de “Pilha”, eu trocaria pelo que eu chamei de “ptr_no”.

int tamPilha=0;

void Inicia (Pilha *topo);
void Insere (Pilha *topo, int num);
void Imprime (Pilha *topo);
bool Vazia (Pilha *topo);

int main (void) {
int i;
Inicia (&topoPilha);
Insere (&topoPilha, 3);
Insere (&topoPilha, 2);
Insere (&topoPilha, 1);
if (Vazia (&topoPilha))
printf("Pilha Vazia\n");
printf("%d\n", tamPilha);
Imprime (&topoPilha);
return 0;
}

void Inicia (Pilha *topo) {
topo = NULL;


Note que acima você alterou o valor da variável topo, que é só visível dentro da função. Se você quisesse ter alterado o valor do argumento a ela passado, você teria de ter feito algo como *topo=NULL;. Entretanto, como você tinha definido Pilha como um tipo que não é um ponteiro, isso daria erro.

Então você já nota que a definição do jeito que eu indiquei (i.e. o typedef declara um tipo que funciona como ponteiro para a estrutura) seria melhor. Mas, além disso, permite também que você use a forma mais usual de construir objetos em C, que é retornando o objeto (que é na verdade um ponteiro) pelo retorno normal da função, e não como parâmetro passado por referência (como fazem fopen(), opendir(), e a própria malloc()). Veja abaixo.

ptr_no Inicia(){
return NULL;
}


Essa função seria usada do seguinte modo.

ptr_no pilha1;
pilha1=Inicia();


Se bem que, como a função apenas coloca um valor nulo, ela na verdade não é lá muito útil.

Por outro lado, se você quisesse que a sua função, ao ser aplicada a uma pilha já existente e não-vazia, esvaziasse a pilha e entregasse uma pilha nova, então ela teria, sim, de receber o indicador do topo por referência.

bool Inicia(ptr_no *topo){
if(!topo){
errno=EINVAL;
return false;
}
if(*topo){
/* Esvazia a pilha. */
}
*topo=NULL;
return true;
}


}

void Insere (Pilha *topo, int num) {


Como você está trabalhando com pilha, recomendo para suas funções nomes que dão ideia de pilha mesmo. Em vez de Insere(), chame a função de push() ou empilha(). Assim, você ajuda outros programadores, falando a mesma linguagem que eles.

	Pilha *aux;
aux = malloc(sizeof(Pilha));
if (aux!=NULL) {
aux->valor = num;
aux->prox = topo;
topo = aux;


Mesma coisa: topo é uma variável que só existe dentro da função. Não adianta alterá-la. Você teria de alterar *topo e, para tanto, o tipo de *topo tem de ser ponteiro.

		tamPilha++;
}
else
printf("Memoria não alocada");
}

bool Vazia (Pilha *topo) {
if (topo->prox == NULL)


Errado, até porque se sua pilha estiver vazia, topo será nulo, e você não poderá aceder ao campo prox.

E mesmo que pudesse, o que indica se o topo é nulo é o próprio valor de topo, não no que vem abaixo do topo!

Pense no sentido do que você está escrevendo. Se você achar que precisa localizar o topo num lugar diferente daquele ao qual você deu o nome de “topo”, tem uma clara discrepância semântica. Ou você corrige a ideia, ou muda o nome da variáveis (chamando-a, sei lá, de “pré-topo”, ou outra coisa ainda mais esotérica).

		return true;
else
return false;
}

void Imprime (Pilha *topo) {


Eu lembro de ter falado sobre isso recentemente aqui no fórum, mas não lembro se foi para você. Se você está oferecendo uma pilha, você não precisa oferecer meios de examinar ou mexer em elementos que não estejam no topo. O conjunto de operações canônicas de pilhas se resume a empilhar, desempilhar e examinar topo (sendo que alguns puristas sugerem que nem mesmo o exame do topo deveria ser permitido, dizendo que o “certo” seria desempilhar o valor, examiná-lo ou usá-lo, e depois reempilhá-lo).

Não que operações como medir tamanho ou varrer elementos pelo meio sejam definitivamente proibidas. Mas se você fizer isso habitualmente, não estará com uma pilha, e sim com uma lista.

	while (topo->prox != NULL) {
printf("%d\n", topo->valor);
topo = topo->prox;
}
}


Quando rodo o programa, ele retorna:
Pilha Vazia
3


Porque você não está mexendo onde pensa estar mexendo.

Procure seguir minhas sugestões.


3. Re: Problema com Estrutura de Dados Pilha em C

joao pedro ache virgili
joaovirgili

(usa Ubuntu)

Enviado em 11/04/2016 - 07:24h

Realmente, não tinha me dado conta de que a estrutura representa apenas um nó e que é mais conveniente nomeá-la assim. Eu sabia que a estrutura não representava uma pilha inteira, porém não tive o costume especificar no código.
O principal erro do meu código é que a variável que eu alterava nas minhas funções só valiam para aquela função, então quando saísse dela, tudo seria perdido, é isso? Assim eu teria que declarar ponteiro e trabalhar com o ponteiro dentro da função?
typedef struct no *ptr_no;

struct no {
int valor;
ptr_no prox;
};

Se eu não utilizar o "typedef struct no *ptr_no;" neste caso, para declarar um ponteiro pro topo da pilha, teria que fazer assim: "struct no *topoPilha;"?
Ao utilizar o typedef struct no*ptr_no, tudo que eu declarar ja será um ponteiro?

E o modo que utilizei no outro código, está errado também? Tenho uma dificuldade ao mexer com ponteiros, e achei este método mais simples que o primeiro, porém neste está dando falha de segmentação. Geralmente quando dá este erro comigo, é quando tento acessar uma memória não alocada, porém a meu ver a lógica está certa.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

struct pilha {
int valor;
struct pilha* prox;
};
struct pilha *topoPilha;
int tamPilha=0;

void Inicia (struct pilha *topo);
void Insere (struct pilha *topo, int num);
void Imprime (struct pilha *topo);
bool Vazia (struct pilha *topo);

int main (void) {
Inicia(topoPilha);
Insere (topoPilha, 1);
Insere (topoPilha, 2);
Insere (topoPilha, 3);
Imprime(topoPilha);
//if (Vazia(topoPilha))
// printf("Pilha Vazia\n");
return 0;
}

void Inicia (struct pilha *topo) {
topo = NULL;
}

void Insere (struct pilha *topo, int num) {
struct pilha *aux = malloc(sizeof(struct pilha));
if (aux != NULL) {
aux->valor = num;
aux->prox = topo;
topo = aux;
printf("oi\n");
}
else
printf("Memoria nao alocada\n");
}

void Imprime (struct pilha *topo) {
//if (Vazia(topoPilha))
//printf("Pilha Vazia\n");
while (topo->prox != NULL) {
printf("%d\n", topo->valor);
topo = topo->prox;
}
}

bool Vazia (struct pilha *topo) {
if (topo->prox == NULL)
return true;
else
return false;
}


Obrigado por analisar meu código, vou levar em consideração tudo que você falou.


4. Re: Problema com Estrutura de Dados Pilha em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/04/2016 - 10:32h

joaovirgili escreveu:

Realmente, não tinha me dado conta de que a estrutura representa apenas um nó e que é mais conveniente nomeá-la assim. Eu sabia que a estrutura não representava uma pilha inteira, porém não tive o costume especificar no código.


Uma Boa Prática -- com direito a letras maiúsculas -- é você ter um código que se auto-documente. Nomes adequados para tipos de dados, funções, variáveis e macros é uma coisa que ajuda a todos, inclusive a você mesmo. Acostume-se com isso. Nos seus programas, vá além da sintaxe correta; dê um sentido claro a tudo o que você codificar.

O principal erro do meu código é que a variável que eu alterava nas minhas funções só valiam para aquela função, então quando saísse dela, tudo seria perdido, é isso?


É um erro importante, mas não sei se dá para dizer que é o principal. Ele decorre de um problema de fundo que é maior: parece que você não sabe muito bem o que está fazendo.

Assim eu teria que declarar ponteiro e trabalhar com o ponteiro dentro da função?


O topo da pilha é móvel? É alocado dinamicamente? Se sim -- e é “sim” no seu caso --, então tem grandes chances de ter de ser um ponteiro.

Uma próxima pergunta seria esta: seu valor tem de ser modificado dentro de uma função? Se sim, ele tem de ser passado por referência. Como, porém, C não tem referências (todos os argumentos de funções são cópias dos valores dos parâmetros), você tem de passar seu endereço (a cópia do endereço usado para chegar a um dado é o mesmo valor de endereço, logo permite chegar ao mesmo dado), e a função tem de ser declarada para receber tal endereço por meio de um ponteiro (ponteiros são tipos de dados que armazenam endereços de objetos). Mas como o dado original já é de um tipo que é ponteiro, então o argumento da função terá de ser um ponteiro para ponteiro, para receber o endereço do objeto ponteiro que se quer modificar.

void func1(int *arg){ /* ... */ }
void func2(int **arg){ /* ... */ }


int *p_var=malloc(sizeof(int)); // Aloca espaço para um inteiro e salva
// endereço do local alocado em em p_var.

func1(p_var); // func1() recebe uma _cópia_ do _valor_ de p_var. Com a
// cópia é possível modificar o conteúdo da memória apontada
// por p_var (usando “*arg” dentro da função), mas o valor de
// p_var não pode ser alterado pela função.

func2(&p_var); // func2() recebe uma cópia do _endereço_ de p_var. Com o
// endereço de p_var, é possível à função alterar tanto o
// valor de p_var (usando “*arg” dentro da função), como do
// conteúdo por ela apontado (usando “**arg”).


typedef struct no *ptr_no;

struct no {
int valor;
ptr_no prox;
};

Se eu não utilizar o "typedef struct no *ptr_no;" neste caso, para declarar um ponteiro pro topo da pilha, teria que fazer assim: "struct no *topoPilha;"?
Ao utilizar o typedef struct no*ptr_no, tudo que eu declarar ja será um ponteiro?


A vantagem de usar typedef é dar clareza ao código por meio da redução do número de símbolos presentes no código, privilegiando visualmente a semântica, em lugar da sintaxe. Seu uso é mais comum quando há múltiplos níveis de ponteiros ou combinações de ponteiros para tipos compostos (estruturas e arrays) ou para funções, e mais ainda quando você têm funções que recebem essas coisas como argumentos.

Existe um benefício adicional, sobretudo quando se desenvolvem bibliotecas: esconder de quem usa o tipo de dados a possível complexidade interna que tal tipo de dados tem. Como isso, ele não se distrai com detalhes de implementação nem fica tentado a manipular diretamente componentes internos de objetos complexos. O tipo FILE, declarado em <stdio.h> e usado pela biblioteca padrão para entrada e saída de dados, é exemplo de typedef assim. Ele é um nome alternativo para uma estrutura interna complexa que mantém informações como buffers, indicadores de estado, e elementos usados para interagir com o sistema operacional. Mas ninguém precisa se preocupar com isso (nem eu mesmo, mexendo com C há 28 anos, jamais precisei).

Contudo, esses benefícios, no fim das contas, são puramente visuais: o novo nome de um tipo é um sinônimo exato do tipo que ele representa. Veja abaixo.

struct exemplo { /* ... */ };
typedef struct exemplo *p_exemplo;
typedef p_exemplo *pp_exemplo;

struct exemplo a, *b, **c, ***d;
p_exemplo e, *f, **g;
pp_exemplo h, *i;

/*
‘a’ tem o tipo “struct exemplo”.
‘b’ e ‘e’ têm o tipo “struct exemplo *”.
‘c’, ‘f’ e ‘h’ têm o tipo “struct exemplo **”.
‘d’, ‘g’ e ‘i’ têm o tipo “struct exemplo ***”.

Adicionalmente, se todos os níveis de ponteiros apontarem para
dados válidos, então podemos derreferenciar os ponteiros para
obter dados dos seguintes tipos:

- “struct exemplo **”: ‘*d’, ‘*g’ e ‘*i’.
- “struct exemplo *”: ‘*c’, ‘**d’, ‘*f’, ‘**g’, ‘*h’ e ‘**i’.
- “struct exemplo”: ‘*b’, ‘**c’, ‘***d’, ‘*e’, ‘**f’, ‘***g’, ‘**h’ e ‘***i’.
*/


E o modo que utilizei no outro código, está errado também?


Sim, também está errado. Prova disso é a falha de segmentação.

Tenho uma dificuldade ao mexer com ponteiros, e achei este método mais simples que o primeiro, porém neste está dando falha de segmentação.


Não se recrimine nem desista. No começo a gente acaba se confundindo um pouco. Nessa fase, quanto mais diagramas to tipo caixa com setinha que aponta para outras caixas você fizer, melhor para você.

Geralmente quando dá este erro comigo, é quando tento acessar uma memória não alocada, porém a meu ver a lógica está certa.


Seu código agora ficou muito parecido com o anterior. Em particular, todos os erros de modificar localmente as cópias recebidas pelas funções, quando o que se queria era modificar os originais, foram mantidos, assim como a falha lógica de pular o topo e seguir direto para o seguinte ao topo na hora de imprimir e os nomes que dizem uma coisa, mas representam outra.

Veja os exemplos que eu mostrei acima, principalmente aquele com as funções func1() e func2(). Todas as suas funções que alteram a pilha devem se parecer com func2(). As que apenas consultam, podem parecer com func1().


5. Re: Problema com Estrutura de Dados Pilha em C

joao pedro ache virgili
joaovirgili

(usa Ubuntu)

Enviado em 11/04/2016 - 16:38h

Consegui! Muito obrigado pela atenção. Segui todas as sugestões, editei o primeiro código e consegui. Só gostaria de confirmar a parte lógica do código, pois é a que mais tenho dificuldade quando o assunto envolve ponteiro, estrutura, funções e suas passagens, se não for abusar da sua vontade. (:

Na estrutura de dados pilha eu crio uma struct que representa o nó da pilha. Declaro um ponteiro para essa struct que apontará para o topo da pilha. Nas funções, eu passo o ponteiro, e, dentro delas altero o valor do ponteiro para que valha para toda a main e não apenas dentro da função. Assim, ao chamar a função diversas vezes, terei um topo diferente para cada função.
Corrija-me se estiver errado, mas o que entendi é isso. Eu estava me confundindo com listas, pois a lista vc precisa apenas de um ponteiro para o início e, a partir dele, chega nos próximos elementos, assim sendo, ele nunca será altera. Por isso o meu código dava certo para listas e errado para pilha.

Muito obrigado pela ajuda, uma ajuda assim é muito importante pra mim!

Só não entendi uma parte que você falou:
ptr_no Inicia(){
return NULL;
}

Essa função seria usada do seguinte modo.

ptr_no pilha1;
pilha1=Inicia();

Se bem que, como a função apenas coloca um valor nulo, ela na verdade não é lá muito útil.

Por outro lado, se você quisesse que a sua função, ao ser aplicada a uma pilha já existente e não-vazia, esvaziasse a pilha e entregasse uma pilha nova, então ela teria, sim, de receber o indicador do topo por referência.

bool Inicia(ptr_no *topo){
if(!topo){
errno=EINVAL;
return false;
}
if(*topo){
/* Esvazia a pilha. */
}
*topo=NULL;
return true;
}



6. Re: Problema com Estrutura de Dados Pilha em C

joao pedro ache virgili
joaovirgili

(usa Ubuntu)

Enviado em 11/04/2016 - 16:57h

Segue o códgio, caso queira dar uma olhada.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

struct no {
int valor;
struct no *prox;
};
typedef struct no *no_ptr;

no_ptr topoPilha;
int tamPilha=0;

void Inicia (no_ptr *topo);
void Empilha (no_ptr *topo, int num);
void Imprime (no_ptr *topo);
bool Vazia (no_ptr *topo);

int main (void) {
int i;
Inicia (&topoPilha);
if (Vazia (&topoPilha))
printf("Pilha Vazia\n");
Empilha (&topoPilha, 3);
Empilha (&topoPilha, 2);
Empilha (&topoPilha, 1);

printf("%d\n", tamPilha);
Imprime (&topoPilha);
return 0;
}

void Inicia (no_ptr *topo) {
*topo = NULL;
}

void Empilha (no_ptr *topo, int num) {
no_ptr aux; //ponteiro para novo no
aux = malloc(sizeof(no_ptr));
if (aux!=NULL) {
aux->valor = num;
aux->prox = *topo;
*topo = aux;
tamPilha++;
}
else
printf("Memoria não alocada");
}

bool Vazia (no_ptr *topo) {
if (*topo == NULL)
return true;
else
return false;
}

void Imprime (no_ptr *topo) {
while (*topo != NULL) {
printf("%d\n", (*topo)->valor);
*topo = (*topo)->prox;
}
}



7. Re: Problema com Estrutura de Dados Pilha em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/04/2016 - 17:15h

joaovirgili escreveu:

Consegui! Muito obrigado pela atenção. Segui todas as sugestões, editei o primeiro código e consegui. Só gostaria de confirmar a parte lógica do código, pois é a que mais tenho dificuldade quando o assunto envolve ponteiro, estrutura, funções e suas passagens, se não for abusar da sua vontade. (:


Então coloque aqui o código que você modificou.

Só não entendi uma parte que você falou:
ptr_no Inicia(){
return NULL;
}


Essa função seria usada do seguinte modo.

ptr_no pilha1;
pilha1=Inicia();


Se bem que, como a função apenas coloca um valor nulo, ela na verdade não é lá muito útil.

Por outro lado, se você quisesse que a sua função, ao ser aplicada a uma pilha já existente e não-vazia, esvaziasse a pilha e entregasse uma pilha nova, então ela teria, sim, de receber o indicador do topo por referência.

bool Inicia(ptr_no *topo){
if(!topo){
errno=EINVAL;
return false;
}
if(*topo){
/* Esvazia a pilha. */
}
*topo=NULL;
return true;
}


Peço que você desconsidere esse trecho. Eu tentei fazer uma analogia com malloc() e realloc(), mas a analogia ficou ruim; além de imperfeita e só criou confusão.


8. Re: Problema com Estrutura de Dados Pilha em C

joao pedro ache virgili
joaovirgili

(usa Ubuntu)

Enviado em 11/04/2016 - 18:40h

Certo. Mandei o código logo ali em cima. E sobre a minha colocação, está correta?

Na estrutura de dados pilha eu crio uma struct que representa o nó da pilha. Declaro um ponteiro para essa struct que apontará para o topo da pilha. Nas funções, eu passo o ponteiro, e, dentro delas altero o valor do ponteiro para que valha para toda a main e não apenas dentro da função. Assim, ao chamar a função diversas vezes, terei um topo diferente para cada função.
Corrija-me se estiver errado, mas o que entendi é isso. Eu estava me confundindo com listas, pois a lista vc precisa apenas de um ponteiro para o início e, a partir dele, chega nos próximos elementos, assim sendo, ele nunca será altera. Por isso o meu código dava certo para listas e errado para pilha.


Após fazer o de pilha, fiz um de Lista Duplamente Encadeada e o resultado foi ótimo. Não tive problemas e implementei bem rápido chegando aos resultados esperados. Segue o código:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

struct no {
int valor;
struct no *prox, *ant;
};
typedef struct no ListaNo;
ListaNo primeiroLista;

void Inicia(ListaNo *primeiro);
void Insere(ListaNo *primeiro, int num);
void Imprime_Frente (ListaNo *primeiro);
void Imprime_Tras (ListaNo *primeiro);
bool Vazia (ListaNo *primeiro);
int Remove_Ultimo (ListaNo *primeiro);
int Remove_Primeiro (ListaNo *primeiro);

int main (void) {
Inicia(&primeiroLista);
return 0;
}

void Inicia (ListaNo *primeiro) {
primeiro = NULL;
}

void Insere (ListaNo *primeiro, int num) {
while (primeiro->prox != NULL)
primeiro = primeiro->prox;
ListaNo *aux = malloc (sizeof(ListaNo));
aux->valor = num;
aux->prox = NULL;
primeiro->prox = aux;
aux->ant = primeiro;
}

void Imprime_Frente (ListaNo *primeiro) {
if (Vazia(&primeiroLista))
printf("Pilha Vazia\n");
else {
printf("Lista de Frente pra trás: \n");
while (primeiro->prox != NULL){
printf("%d ", (primeiro->prox)->valor);
primeiro = primeiro->prox;
}
printf("\n");
}
}

void Imprime_Tras (ListaNo *primeiro){
if (Vazia(&primeiroLista))
printf("Pilha Vazia\n");
else{
while (primeiro->prox != NULL)
primeiro = primeiro->prox;
printf("Lista de Tras pra Frente\n");
while (primeiro->ant != NULL){
printf("%d ", primeiro->valor);
primeiro = primeiro->ant;
}
printf("\n");
}
}

bool Vazia (ListaNo *primeiro) {
if (primeiro->prox == NULL)
return true;
else
return false;
}

int Remove_Ultimo (ListaNo *primeiro) {
if (Vazia(&primeiroLista))
printf("Pilha Vazia\n");
else {
while (primeiro->prox != NULL)
primeiro = primeiro->prox;
(primeiro->ant)->prox = NULL;
return primeiro->valor;
}
}

int Remove_Primeiro (ListaNo *primeiro){
if (Vazia(&primeiroLista))
printf("Pilha Vazia\n");
else {
primeiro = primeiro->prox;
(primeiro->ant)->prox = primeiro->prox;
primeiro->ant = NULL;
return primeiro->valor;
}
}

Fiz com base naquilo que eu havia dito. Na lista, meu ponteiro será para o primeiro elemento e ficará fixo lá, assim as alterações que faço são apenas dentro da função, sem alterar na main. Por outro lado, na pilha, o meu ponteiro para topo fica sempre variando, por isso tenho que alterar ele dentro da função e para todo o programa.


Repito, muito obrigado pelas dicas, me ajudou muito! Até ontem estava meio perdido e você me fez ver os erros, agora tudo ficou mais claro.


9. Re: Problema com Estrutura de Dados Pilha em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/04/2016 - 19:01h

No código da pilha, a função de impressão está errada. Você percorre os elementos usando o ponteiro que deveria apontar para o topo. No final do percurso, a pilha não vai mais estar acessível, pois o topo terá chegado à base (NULL).

Para completar o equívoco, aquela memória que ficou inatingível não foi liberada. Os dados estão lá, ocupando memória do processo, mas completamente inacessíveis.

Corrija isso.


10. Re: Problema com Estrutura de Dados Pilha em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/04/2016 - 19:07h

Com relação ao código da lista duplamente encadeada, todos os conselhos que eu dei a respeito de pilha valem também para listas ou filas. Até porque, como você já deve ter notado, pilhas e filas são casos particulares de listas.


11. Re: Problema com Estrutura de Dados Pilha em C

joao pedro ache virgili
joaovirgili

(usa Ubuntu)

Enviado em 11/04/2016 - 19:13h

paulo1205 escreveu:

No código da pilha, a função de impressão está errada. Você percorre os elementos usando o ponteiro que deveria apontar para o topo. No final do percurso, a pilha não vai mais estar acessível, pois o topo terá chegado à base (NULL).

Para completar o equívoco, aquela memória que ficou inatingível não foi liberada. Os dados estão lá, ocupando memória do processo, mas completamente inacessíveis.

Corrija isso.


Verdade, não tinha me tocado disso. Devo então declara um auxiliador para percorrer a pilha, né?






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts