Ir ao conteúdo

Posts recomendados

Postado

Olá,

 

Estou fazendo uma programa que o objetivo é copiar os elementos de uma lista encadeada em outra lista encadeada.

Criei uma função chamada copia que faria essa parte, o problema é que a maneira como eu fiz só está copiando o primeiro elemento inserido na lista original.

Acredito que seja porque a função só está fazendo o processo de inserção uma vez, quando retorna "novo", mesmo ela tendo lido toda a lista original, então como o primeiro elemento da lista original é o último que ela lê, então é o único que insere.

 

Eu tentei de tudo aqui pra fazer com que ela insira todos os elementos da lista original, mas todas as outras formas que eu tentei, a função nem insere nada, esse código foi o que eu cheguei mais próximo de acertar:

 

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

typedef struct lista {
   int info;
   struct lista* prox;
} Lista;

Lista* lista_cria() {
   return NULL;
}

Lista* lista_insere (Lista* l, int i) {
   Lista* novo = (Lista*) malloc(sizeof(Lista));
   novo->info = i;
   novo->prox = l;
   return novo;
}

void lista_imprime (Lista *l) {
   Lista *p;
   for (p = l; p; p = p->prox)
       printf("%d\n", p->info);
}


Lista* lista_copia (Lista *l, Lista* l2) {

   int j;
   Lista *p;
   Lista* novo = (Lista*) malloc(sizeof(Lista));

   for (p = l; p; p = p->prox) {

    j = p->info;

   novo->info = j;
   novo->prox = l2;
   }
   return novo;


}


Lista* lista_libera (Lista* l) {
   Lista* p = l;
   while (p != NULL) {
       Lista* t = p->prox;
       free(p);
       p = t;
   }
   return NULL;
}

int main() {
   Lista* l;
   Lista* l2;
   
   l = lista_cria();
   l = lista_insere(l, 25);
   l = lista_insere(l, 47);
   l = lista_insere(l, 63);
   l = lista_insere(l, 84);
   l = lista_insere(l, 92);

     printf("\nLista1:\n");
     lista_imprime(l);


     l2 = lista_cria();

     l2 = lista_copia(l, l2);

     printf("\n\nLista2:\n");
     lista_imprime(l2);


   lista_libera(l);
   lista_libera(l2);

   return 0;
}

 

Postado

@HenriSp Bom dia.

 

11 horas atrás, HenriSp disse:

é autoaprendizagem mesmo.

 

O que você chamou de lista é um nó.

typedef struct
{
 	PVoid informacao;
 	PNo   proximo;
}
No, * PNo;

 

Com relação a função lista_copia:

Lista * lista_copia (Lista * l, Lista * l2) {

   int j;
   Lista * p;
   Lista * novo = (Lista *) malloc (sizeof (Lista));

   for (p = l; p; p = p->prox) {

    j = p->info;

   novo->info = j;
   novo->prox = l2;
   }
   return novo;


}
  1. Não precisa da variável j.
  2. Antes de alocar espaço para novo lista é preciso precisar o espaço; no caso, pretende copiar l então determine o tamanho de l, só para assim depois copia-lo.
  3. l2 não faz sentido; se a intenção é copiar l e retorna a copia por escape da função (ao sair).
  4. Comente suas linhas de código.
Postado

@Mauro Britivaldo Bom dia, obrigado por responder.

 

Não entendi direito.

 

Por quê é um nó e não uma lista? Eu segui um passo-a-passo para a criação de uma lista encadeada.

Como assim  "precisar o espaço"? O tamanho de l vai depender de quantos elementos for inserido nela, não é pré-determinado.

E o que seria "copia por escape"?

Postado

Olá!

 

Talvez você não tenha entendido bem o que significa copiar uma lista para outra. E também não tenha definido exatamente o que pretende fazer...

 

Lista* lista_copia (Lista *l, Lista* l2)
{
   int j;
   Lista *p;
   Lista* novo = (Lista*) malloc(sizeof(Lista));

   for (p = l; p; p = p->prox)
   {
       j = p->info;
       novo->info = j;
       novo->prox = l2;
   }
   return novo;
}

Um dos elementos da lista é o ponteiro ou os ponteiros para os itens antes ou depois. E tem os dados de cada nó. Sua função que copia a lista pretende copiar a lista toda ou apenas os endereços?

Em muitos casos os elementos da lista são enormes, como grandes cadastros de coisas com muitas informações sendo acessadas. Então faz sentido às vezes copiar apenas a lista de ponteiros para, por exemplo, acessar numa ordem específica, como ler um cadastro pela ordem de CEP para programar entregas.

 

Copiando a lista inteira

 

Copiar a lista inteira como operação "atômica" não existe: você copia um por um e põe na lista, e aí poderia derivar direto de sua função que percorre a lista

 

Em lista_imprime() da lista original chame lista_insere() da nova lista. Só isso. Não pode dar errado ou uma das duas já teria dado errado com a lista original... Apenas crie lista_copia(Lista* origem, Lista* destino) igualzinho a lista_imprime(Lista* original) e lá dentro chame lista_insere(Lista* destino).

 

Postado
4 horas atrás, HenriSp disse:

Por quê é um nó e não uma lista?

 

Porque não tem as características básicas de uma:

1. Tamanho (capacidade inicial)

2. Primeiro elemento (cabeça da lista)

3. Últimos elemento (fim da lista)

4. Elemento atual (posição de leitura e gravação)

5. Quantidade atual de elementos (espaço ocupado).

 

Tem a de um nó:

1. Informações

2. Próximo

 

Você pode continuar chamando de lista que muitos vão aceitar. Refiro-me a struct Lista.

 

4 horas atrás, HenriSp disse:

Eu segui um passo-a-passo para a criação de uma lista encadeada

 

Já vi em muitos livros, apostilas e na internet com mesmo conceito e identificador de lista um nó. Já esperava essa resposta.

 

4 horas atrás, HenriSp disse:

Como assim  "precisar o espaço"? O tamanho de l vai depender de quantos elementos for inserido nela, não é pré-determinado.

 

O mesmo não se diz da copia. Se é uma copia então preciso saber se há recurso para ela, pois senão nem começo.

 

Se pensou em copiar dinâmicamente então tudo bem, falhou miseravelmente, mas nem tudo está perdido e aprender é assim mesmo.

 

Parece que vai inserir em l2. Você aloca espaço para isso antes? Não! É só olhar pra função main onde o comando criar lista retorno null! É isso mesmo? Putz!!! Por essa razão perguntei se tem um professor por traz dessa função miserável.

 

4 horas atrás, HenriSp disse:

E o que seria "copia por escape"?

 

Isso não é importante é só uma gíria desculpa. Seria melhor ter dito: retorno pela return da função o ponteiro novo. Funçõe retornam dados de duas maneiras: return ou parâmetro de saída.

 

Obrigado.

Postado

Confiando no seu  próprio código você podia ter escrito 

Lista* lista_imprime_e_copia( Lista* original, Lista* nova )
{
    Lista* p;
    int i = 0;
    for (p = original; p; p = p->prox)
    {
        printf("%3d  ", p->info);
        nova = lista_insere(nova, p->info);
        if (i % 5 == 4) printf("\n");
        i += 1;
    }
    printf("\n%d itens na lista\n", i);
    return nova;
}

Claro que não era pra imprimir mas assim você já vai testando enquanto escreve...

 

Suas funções já funcionam porque criou a lista original e mostrou. Então o código copiado de lista_imprime() e o código que chama lista_insere() deve funcionar. E funciona

Esse código 
 

    // o que podia ser
    Lista* original = NULL;
    Lista* copia = NULL;

    for (int i=1; i<= 9; i++)
    {
        original = lista_insere(original, i);
    }
    printf("\n\n==> Lista Original:\n");
    lista_imprime(original);

    printf("\n\n==> Mostra e Copia lista original:\n");
    copia = lista_imprime_e_copia(original, copia);

    printf("\n\n==> Lista Copiada:\n");
    lista_imprime(copia);

    lista_libera(original);
    lista_libera(copia);


Usando o que você já escreveu mostra

==> Lista Original:
9
8
7
6
5
4
3
2
1


==> Mostra e Copia lista original:
  9    8    7    6    5
  4    3    2    1
9 itens na lista


==> Lista Copiada:
1
2
3
4
5
6
7
8
9

Entenda que sua implementação de lista ainda está longe de seu útil.

Postado

@Mauro Britivaldo Certo, é que eu vi várias explicações de como fazer listas e eram todas bem parecidas. Eu ainda estou verde em linguagem c, e já tô querendo aprender estrutura de dados rsrs. Muito obrigado pela informações, me ajudou bastante a clarear as coisas.

 

@arfneto Muito obrigado mesmo, consegui fazer funcionar  direitinho. Aprendi bastante coisa nesse tópico, eu nem sabia que eu podia usar uma função dentro de outra função fora do método main. Acabei aprendendo mais coisas do que a minha dúvida inicial.

 

Muito obrigado aos dois.

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!