PDA

Visualizza la versione completa : [C] Utilizzare puntatori singoli e doppi


edigenov
11-07-2007, 11:10
Ciao a tutti, fra 2 giorni avrò l'esame su fondamenti di informatica ed ho un grosso dubbio, vi prego aiutatemi!

Non riesco a capire quando usare il puntatore singolo rispetto a quello doppio nelle strutture dati tipo liste ed alberi. Io ragiono in questo modo:
Se per esempio ho questo:

typedef struct lista_ele{
int ele;
lista_ele *prox;
}lista;

chiamo la funzione conta che mi scorre una lista in questo modo:

void conta(lista *pun){
int i=0;

if(pun->prox!=NULL){
pun=pun->porx;
i++;
}
}
}

quando il controllo torna al client, il puntatore alla lista è modificato o no?
e se invece la scrivo così:

lista conta(lista *pun){
int i=0;

if(pun->prox!=NULL){
pun=pun->porx;
i++;
}
}
return pun;
}

o anche così:

lista conta(lista *pun){
int i=0;
lista *temp=pun;

if(temp->prox!=NULL){
temp=temp->porx;
i++;
}
}
return pun;
}

Spiegatemi quali delle tre funzionano senza modificare il puntatore alla lista e perchè!!!!!

aiutatemi vi prego, spiegatemi questi dubbi...cmq questa è la prima domanda poi ne ho un altra sul doppio puntatore!

XWolverineX
11-07-2007, 12:48
Tutte e 3 modificano i dati, poichè i puntatori si passano solo per riferimento.
Se vuoi che il puntatore non venga modificato puoi
[list=a]
Creare un puntatore alla struttura, lo allochi, fai un memcpy e usi quello per contare (e dopo lo elimini, ovviamente)
Crei un puntatore temporaneo in cui memorizzi il primo elemento della lista. Scorri la lista per contare, e dopo riassegni il puntatore a quello temporaneo per farlo tornare allo stato iniziale
[/list=a]

In pratica
Esempio 1



typedef struct lista_ele
{
int ele;
lista_ele *prox;
} lista;

int conta(lista *pun)
{
int i=0;
lista *tmp = malloc(sizeof(lista)); //Non sono molto sicuro
memcpy(pun,tmp,sizeof(lista)); //Che qui vada bene
if (tmp->Prox != NULL)
{
i++; tmp=tmp->Prox;
}
free(tmp);
return i;
}




Modo 2...




typedef struct lista_ele
{
int ele;
lista_ele *prox;
} lista;

int conta(lista *pun)
{
int i=0;
lista *tmp = malloc(sizeof(lista)); //Non sono molto sicuro
memcpy(lista,tmp,sizeof(lista));

if (pun->Prox != NULL)
{
i++; pun=pun->Prox;
}
memcpy(tmp,pun,sizeof(lista));
free(tmp);
return i;
}


L'ho pensato al volo quindi potrebbe anche essere tutto sbagliato :D

edigenov
11-07-2007, 18:05
comunque perchè invece a volte si usa il doppio puntatore o meglio, l'inserimento e l'eliminazione di un elemento da una lista si risolve solo con il doppio puntatore?

Squall1988
12-07-2007, 02:25
Non è vero, inserimento e cancellazione si fanno anche con il puntatore singolo...
se ho ben capito, per doppio intendi che oltre al puntatore al prossimo elemento c'è anche quello al precedente... in questo caso i vantaggi sono legati all'efficienza di alcune routine, ma non all'inserimento od alla cancellazione, che hanno costo O(1) se si conosce il nodo di riferimento (dopo cui inserire o da cancellare)

edigenov
12-07-2007, 10:43
no no, non intendo puntatore al precedente e al successivo, la lista bidirezionale è altro;
io intendo per esempio che per eliminare elementi da una lista l'unica modalità che mi funziona è questa:

#include <stdio.h>
#include <malloc.h>

typedef struct lista_ele{
int val;
struct lista_ele *prox;
}lista;

lista *crea_lista();
void visualizza(lista *);
void elimina(lista **);

main(){
int ter;

lista *punt_lista;
punt_lista=crea_lista();
visualizza(punt_lista);
elimina(&punt_lista);
visualizza(punt_lista);
}


lista *crea_lista(){

lista *p,*paus;
lista x;

printf("Inserisci valore o zero per terminare: ");
scanf("%d",&x.val);

if(x.val==0)
p=NULL;
else{
p=(lista *)malloc(sizeof(lista));
p->val=x.val;
paus=p;

while(x.val!=0){
printf("Inserisci valore o zero per terminare: ");
scanf("%d",&x.val);
if(x.val!=0){
paus->prox=(lista *)malloc(sizeof(lista));
paus=paus->prox;
paus->val=x.val;
}
else
paus->prox=NULL;
}
}
return (p);

}


void visualizza(lista *p){

int cont=0;
printf("\n------");

while(p!=NULL){
cont++;
printf("%d",p->val);
printf("->");
p=p->prox;
}
printf("NULL\n\n");
}


void elimina(lista **pun){
int t;
lista *paus;

printf("Inserisci ele da eliminare: ");
scanf("%d",&t);

while(*pun!=NULL && (*pun)->val!=t)
pun=&(*pun)->prox;

paus=*pun;
*pun=(*pun)->prox;
free(paus);
}


Altri metodi non conosco ...aiutatemi, datemi un'altra soluzione a questa e ve ne sarò gratoooo

Loading