Jump to content
thinkabout

Duplicar uma lista

Recommended Posts

thinkabout

Ele cria-me a lista, mas depois não mete para lá informação.

Deve me estar a escapar alguma coisa sobre copia de estruturas.

---

Edited...

Hum a cada atribuição tenho que arranjar mais um bloco de memória, vou trato disso, não sei se esse será o único erro.

// Função que duplica a lista
void duplicalista(pno lista)
{
   pno aux_lista;
   pno listaduplicada=NULL;
   pno aux_listaduplicada=NULL;

   // Vejo quem tenho na lista
   puts("");
   ListaPaciente(lista);
   // Aponta os ponteiros para o mesmo sitio.

   aux_lista=lista;
   printf("lista aponta para a memoria %p e aux lista aponta para %p \n",lista, aux_lista);
   system("Pause");

   // Arranjo espaço para a nova fila
   if ((listaduplicada=(pno)malloc(sizeof(no)))==NULL) 
   {
       printf("erro na alocacao de memoria"); 
   } 
   else
   {
       listaduplicada->prox=NULL;
   }
   // Aponta os ponteiros para o mesmo sitio.
   aux_listaduplicada=listaduplicada;
   // Confirmo que eles estão apontar para o mesmo sitio
   printf("lista aponta para a memoria %p e aux lista aponta para %p \n",listaduplicada, aux_listaduplicada);
   system("Pause");

   while (aux_lista != NULL)
   {
       aux_listaduplicada=aux_lista; // Ganha o valor que está nessa posição (?!?)
       aux_listaduplicada=aux_listaduplicada->prox; // A onde vou guardar a informação também vai andar para a frente
       aux_lista=aux_lista->prox; // A lista original anda uma posição para a frente.
   }

   puts("Agora vem a lista duplicada");
   ListaPaciente(listaduplicada);
   printf("lista aponta para a memoria %p e aux lista aponta para %p \n",listaduplicada, aux_listaduplicada);

}

Edited by thinkabout

Share this post


Link to post
Share on other sites
Rui Carlos

No ciclo parece-me que te limitas a alterar as variáveis locais.

Adicionalmente, se queres duplicar a lista, à partida terás que alocar espaço novamente para cada nodo da lista original.

Share this post


Link to post
Share on other sites
thinkabout

Garbage.

Postei aqui código, mas reparei logo depois em 2 ou 3 erros removi o mesmo.

Amanhã volto a luta que isto hoje já está para o lado do dopado.

Edited by thinkabout

Share this post


Link to post
Share on other sites
thinkabout

Ele já me duplica a lista, sei que me falta depois o resto da função para o elemento seguinte mas para já tenho um problema que ele copia-me tudo de uma vez.

Quando vou fazer a verificação do nr de elementos das listas um dá 3 e outro dá 1, quando deviam dar as duas 1 para já.

O output de texto é igual na duas

output

um

dois

tres

output 2

um

dois

tres

printf("%d \n",(imprimirnrtotaldeelementos(lista))); // Se o exemplo for 1,2,3 dá 3
printf("%d \n",(imprimirnrtotaldeelementos(listaduplicada))); // Se o exemplo for 1,2,3 dá 1

// Função que duplica a lista
void duplicalista(pno lista)
{

pno listaduplicada=NULL; // Para ficar com o começo da nova lista
pno aux_listaduplicada=NULL; // Para depois andar par a par com o lista_aux para andar a copiar a posição.
pno lista_aux;  // Para depois andar par a par com o aux_listaduplicada para andar a copiar a posição.

lista_aux=lista; // Ganha a cabeça da lista

// Apontei os ponteiros para o mesmo sitio. Debug
printf("lista aponta para a memoria %p e aux lista aponta para %p \n",lista, lista_aux);
system("Pause");

// Vejo quem tenho na lista Debug
puts("ca esta a lsita a lista original");
ListaPaciente(lista);


while (lista_aux != NULL)
{

	if ((listaduplicada=(pno)malloc(sizeof(no)))==NULL) 
	{
		printf("erro na alocacao de memoria"); 
	} 
	else
	{
		listaduplicada->prox=NULL; // O novo bloco como vai ser o último da fila fica sempre a apontar para NULL.

		if (aux_listaduplicada==NULL) 
		{
			aux_listaduplicada=listaduplicada;
			memcpy(aux_listaduplicada, lista_aux, (sizeof(no)));
			printf("listaduplicada aponta para a memoria %p e aux_listaduplicada aponta para %p \n",listaduplicada, aux_listaduplicada);

			puts("ca vem a lista duplicada");
			ListaPaciente(listaduplicada);
			system("Pause");

		}   
	}
	lista_aux=lista_aux->prox; // A lista original anda uma posição para a frente.
}
printf("%d \n",(imprimirnrtotaldeelementos(lista))); // Se o exemplo for 1,2,3 dá 3
printf("%d \n",(imprimirnrtotaldeelementos(listaduplicada))); // Se o exemplo for 1,2,3 dá 1

}

Share this post


Link to post
Share on other sites
thinkabout

Isto daqui bocado começa a parecer SPAM, com um já funciona bem.

Mas devo estar a fazer asneira com o aux_listaduplicada quando entro no else para os elementos depois do primeiro.

Nome dos pacientes

=================================

1

2

3

4

=================================

ca vem a lista duplicada

Nome dos pacientes

=================================

1

=================================

Press any key to continue . . .

ca vem a lista duplicada

Nome dos pacientes

=================================

2

=================================

Press any key to continue . . .

ca vem a lista duplicada

Nome dos pacientes

=================================

3

=================================

Press any key to continue . . .

ca vem a lista duplicada

Nome dos pacientes

=================================

4

=================================

Press any key to continue . . .

4

1

// Função que duplica a lista
void duplicalista(pno lista)
{
       pno listaduplicada=NULL; // Para ficar com o começo da nova lista
       pno aux_listaduplicada=NULL; // Para depois andar par a par com o lista_aux para andar a copiar a posição.
       pno lista_aux;  // Para depois andar par a par com o aux_listaduplicada para andar a copiar a posição.

       lista_aux=lista; // Ganha a cabeça da lista

       // Apontei os ponteiros para o mesmo sitio. Debug
       printf("lista aponta para a memoria %p e aux lista aponta para %p \n",lista, lista_aux);
       system("Pause");

       // Vejo quem tenho na lista Debug
       puts("ca esta a lsita a lista original");
       ListaPaciente(lista);


       while (lista_aux != NULL)
       {

               if ((listaduplicada=(pno)malloc(sizeof(no)))==NULL)
               {
                       printf("erro na alocacao de memoria");
               }
               else
               {
                       listaduplicada->prox=NULL; // O novo bloco como vai ser o último da fila fica sempre a apontar para NULL.

                       if (aux_listaduplicada==NULL)
                       {
                               aux_listaduplicada=listaduplicada; // Meto os ponteiros a apontar para o mesmo sitio.
                               memcpy(aux_listaduplicada, lista_aux, (sizeof(listaduplicada)));                                                          /*               printf(" MARCA 1 - listaduplicada aponta para a memoria %p e aux_listaduplicada aponta para %p \n",listaduplicada, aux_listaduplicada);*/
                               aux_listaduplicada=aux_listaduplicada->prox=NULL;
                               puts("ca vem a lista duplicada");
                               ListaPaciente(listaduplicada);
                               system("Pause");

                       }  
                           else
                           {
                               //printf("MARCA 2 o conteudo de aux_listaduplicada e %s, e o conteudo de lista_aux e %s \n", listaduplicada,lista_aux );
                               memcpy(aux_listaduplicada, lista_aux, (sizeof(listaduplicada)));

                           }

               }
               lista_aux=lista_aux->prox; // A lista original anda uma posição para a frente.

       }    
       printf("%d \n",(imprimirnrtotaldeelementos(lista))); // Se o exemplo for 1,2,3 dá 3
       printf("%d \n",(imprimirnrtotaldeelementos(listaduplicada))); // Se o exemplo for 1,2,3 dá 1

}

Share this post


Link to post
Share on other sites
Rui Carlos

Tens aí uma carrada de funções de I/O que só fazem confusão, e não deviam estar misturadas com a computação propriamente dita.

Isto

if ((listaduplicada=(pno)malloc(sizeof(no)))==NULL)

era desnecessário estar tudo junto. Coloca a alocação separada (adicionalmente, não era suposto fazeres cast do resultado do malloc).

Quanto ao resto, depois de colocares o prox a NULL, devias colocar o apontador do nodo anterior a apontar para o actual.

Qualquer coisa como

anterior_listaduplicada->prox = listaduplicada;

A condição

if (aux_listaduplicada==NULL)

falha alguma vez?

O algoritmo que precisas deve ser alguma coisa do género:

lista_duplicada = NULL;

for(nodo_original = lista_original; nodo_original != NULL; nodo_original = nodo_original->prox) {
 nodo = malloc(...);
 if(lista_duplicada == NULL) {  // primeiro nodo, logo é a cabeça da nova lista, que temos que guardar
lista_duplicada = nodo;
 }
 else {  // se não é o primeiro, então existe um nodo anterior, que temos que colocar a apontar para este que acabamos de alocar
nodo_anterior->prox = nodo;
 }
 nodo->conteudo = nodo_original->conteudo;  // copia o conteúdo do nodo, sem fazer deep copy; provavelmente precisa de ser alterado
 nodo->prox = NULL; // para já fica a NULL, mas na próxima iteração, podemos ter que o ligar ao próximo nodo, se existir
 nodo_anterior = nodo;  // guarda o nodo actual, pois se houver mais uma iteração, teremos que actualizar o valor de prox
}

Deixei de fora a verificação do malloc para simplificar.

Share this post


Link to post
Share on other sites
KTachyon

Pois, no fundo não estás a duplicar a lista, estás a colocar nós aleatoriamente em memória. Se queres duplicar a lista tens sempre que guardar uma referência para o primeiro nó da lista, e eu não vejo isso a acontecer. Repara também que, depois de alocarea a memória e a copiares pela primeira vez para aux_listaduplicada, estás a fazer o seguinte:

aux_listaduplicada=aux_listaduplicada->prox=NULL;

Ou seja, aux_listaduplicada volta a ser NULL, resultando que nunca entras no else (independentemente daquilo que pretendes de facto lá fazer.

A ideia é:

1. alocas memória para a struct;

2. copias o nó para esse espaço em memória;

3. se o ponteiro inicial for nulo:

3.1. colocas esse ponteiro a apontar para essa memória;

3.2. colocas um ponteiro auxiliar a apontar para o ponteiro inicial;

4. se o ponteiro inicial não for nulo:

4.1 colocas o próximo do ponteiro auxiliar a apontar para essa memória;

4.2 colocas o ponteiro auxiliar a apontar para o proximo do ponteiro auxiliar;

5. Repete até não haverem mais nós;

6. Retorna o ponteiro inicial.


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.