Curiosità funzione rimozione in testa da lista;

di Anonimizzato9570 il
13 risposte
Salve, sto studiando la gestione di una lista, e ho un dubbio per quanto riguarda la funzione per rimuovere dalla testa:
template <class t>
bool list<t>::removeFront(t & value){
	if (isEmpty()){
		return false;
	}
	else{
		if(firstPtr==lastPtr)//se i due puntatori sono uguali c'è un solo nodo che
			firstPtr=lastPtr=0;//se rimosso svuota la lista;
		nodo <t> *tempPtr=firstPtr;
		firstPtr=firstPtr->next;
		value=tempPtr->dato;//restituisce il contenuto del nodo cancellato
		delete tempPtr;
		return true;
		
		
	}
	
}
si usa passare il parametro value per tenere traccia del contenuto del nodo cancellato?
non mi spiego quale potrebbe essere la sua utilità

13 Risposte

  • Supponiamo che ti serva per poter presentarlo a video dopo averlo rimosso. Ecco che ti serve sapere il valore che aveva il nodo in testa.
  • Si, ma se non ha significati funzionali per il momento lo ometto
  • Certo. se vedi anche lo std::list::pop_front non ritorna nulla e rimuove l'elemento in testa.
  • Mi sorge un altro dubbio: nella funzione l'unico delete lo facciamo sul puntatore tempPtr che è stato allocato per mantenere momentaneamente una copia di firstPtr;
    mentre invece non eliminiamo "fisicamente" il nodo cancellato bensì lo scolleghiamo dalla lista perdendo ogni informazione su di esso, quindi è ancora presente in memoria?
  • Si ed è una delle cose che non dovresti mai fare. Supponiamo una lista di 1 milione di elementi. pian pianino tu scolleghi la testa finchè non ne rimane nessuno nella lista ma hai sporcato la memoria in un modo mostruoso lasciando pezzi quà e là che sono nella terra di nessuno. Magari poi ti meriti un bel augurio dall'utilizzatore che vedrà il tuo programma uttilizzare giga di ram per fare niente.
  • skynet ha scritto:


    Si ed è una delle cose che non dovresti mai fare. Supponiamo una lista di 1 milione di elementi. pian pianino tu scolleghi la testa finchè non ne rimane nessuno nella lista ma hai sporcato la memoria in un modo mostruoso lasciando pezzi quà e là che sono nella terra di nessuno. Magari poi ti meriti un bel augurio dall'utilizzatore che vedrà il tuo programma uttilizzare giga di ram per fare niente.
    si, infatti mi sembra strano, questo è un esempio tratto dal libro" c++ how to program" daitel & daitel. Non so perchè hanno mostrato la gestione in questo modo
  • Il linguaggio C++ è severo in questo: ad ogni new deve corrispondere un delete e and ogni new [] un delete []. Se non si rispettano queste regole si va a finire del calderone del "undefined behavior" ovvero comportamento non definito.
  • Guarda ti passo il codice che ho riportato pari pari dal manuale

    la classe nodo
    /*
     * nodo.h
     *
     *  Created on: 26/giu/2013
     *      Author: gen
     */
    
    #ifndef NODO_H_
    #define NODO_H_
    
    template <class t> class list;//predichiarazione necessaria per la funzione friend
    
    template <class t>
    class nodo{
    	friend class list <t>;
    public:
    	nodo(const t &);//riceve in ingresso un tipo di dato generico
    	t getData()const;
    private:
    	t data;
    	nodo <t> *next;
    };
    
    //costruttore
    template <class t>
    nodo<t>::nodo(const t & info):data(info),next(0){}
    
    template <class t>
    t nodo<t>::getData()const{
    return data;
    }
    #endif
    questa è la classe lista :
    /*
     * lista.h
     *
     *  Created on: 26/giu/2013
     *      Author: gen
     */
    
    #ifndef LISTA_H_
    #define LISTA_H_
    
    #include <iostream>
    #include "nodo.h"
    using namespace std;
    
    template <class t>
    class list{
    public:
    	list();
    	 ~list();
    	 void insertFront(const t &);
    	 void insertBack(const t&);
    	 bool removeFront(t&);
    	 bool removeBack(t&);
    	 bool isEmpty()const;
    	 void print() const;
    private:
    	 nodo <t> *firstPtr;
    	 nodo <t> *lastPtr;
    
    	 //funzione di utiliy per allocare un nuovo nodo
    	 nodo <t> *getNewNodo(const t&);
    private:
    };
    
    template <class t>
    nodo <t>* list<t>::getNewNodo(const t& info){
    	return new nodo <t>  (info);
    }
    
    
    template <class t>
    list <t>::list():firstPtr(0),lastPtr(0){}
    
    template <class t>
    list <t>::~list(){
    	if(!isEmpty()){
    		cout<<"\nDistruggo tutti i nodi\n";
    		nodo <t> *currentPtr;
    		nodo <t> *tempPtr;
    		while(currentPtr!=0){
    			tempPtr=currentPtr;
    			cout<<"\n"<<tempPtr;
    			currentPtr=currentPtr->next;
    			delete tempPtr;
    		}
    	}
    	cout<<"\n Tutti i nodi sono distrutti\n";
    }
    
    
    template <class t>
    void list <t>::insertFront(const t& value){
     nodo <t> *newPtr=getNewNodo(value);
     if(isEmpty())
    	 firstPtr=lastPtr=newPtr;
     else{
    	newPtr->next=firstPtr;
    	firstPtr=newPtr;
     	 }
    }
    
    template <class t>
    void list<t>::insertBack(const t& value){
    	nodo <t> *newPtr;//creo un punatore ad un nuovo nodo di tipo t
    	newPtr=getNewNodo(value);//e gli assegno l'indirizzo del nuovo nodo creato;
    	if(isEmpty())
    		firstPtr=lastPtr=newPtr;
    	else{
    		lastPtr->next=newPtr;
    		lastPtr=newPtr;
    	}
    
    }
    
    template <class t>
    bool list<t>::removeFront(t & value){
    	if (isEmpty()){
    		return false;
    	}
    	else{
    		if(firstPtr==lastPtr)//se i due puntatori sono uguali c'è un solo nodo che
    			firstPtr=lastPtr=0;//se rimosso svuota la lista;
    		nodo <t> *tempPtr=firstPtr;
    		firstPtr=firstPtr->next;
    		value=tempPtr->data;//restituisce il contenuto del nodo cancellato
    		delete tempPtr;
    		return true;
    	}
    }
    template <class t>
    bool list<t>::removeBack(t& value){
    	if(isEmpty())
    		return false;
    	else{
    		nodo <t> *tempPtr=lastPtr;
    		if(firstPtr==lastPtr)
    			firstPtr=lastPtr=0;
    		else{
    
    			nodo<t> *currentPtr=firstPtr;
    			while(currentPtr->next!=lastPtr)
    				currentPtr=currentPtr->next;
    			lastPtr=currentPtr;
    			currentPtr->next=0;
    		}
    		value=tempPtr->data;
    		delete tempPtr;
    	}
    }
    
    
    template <class t>
    bool list <t>::isEmpty()const{
    	return firstPtr==0;
    }
    
    template <class t>
    void list<t>::print()const{
    	cout<<"\nStampa della lista: \n";
    	if(isEmpty()){
    		cout<<"\nLa lista è vuota\n";
    		return;
    	}
    	nodo <t> *currentPtr=firstPtr;
    	while(currentPtr!=0){
    		cout<<currentPtr->data<<"  ";
    		currentPtr=currentPtr->next;
    	}
    }
    
    #endif /* LISTA_H_ */
    a me non sembra rispetti molto ciò che mi hai appena detto
  • Nel distruttore non ho inizializzato currentPtr : nodo <t> *currentPtr=firstPtr;
  • Come no? non vedi che c'è il delete di tutti i nodi?
  • Si, nel distruttore,ma se non distruggessi mai la lista ed avessi una memoria molto limitata,, dopo un certo numero di insert e remove esaurirei lo spazio no?
  • Per quello che new emmette un eccezione se non puó allocare memoria che dev'essere intercettato.
  • Tutto chiaro
Devi accedere o registrarti per scrivere nel forum
13 risposte