Liste: spostare un elemento di una lista in coda o in testa.

di il
8 risposte

Liste: spostare un elemento di una lista in coda o in testa.

Salve a tutti, sono nuovo qui e ho qualche domanda da farvi sulle liste astratte in C++.
Allora, vorrei sapere come è possibile spostare un indirizzo di una lista, per metterlo in coda o in testa:
Nell'header file ho creato una struct, fatta in questo modo:

struct Foto{
    Foto * pun;//puntatore della struct
    char * file; //nome file della foto da salvare nella lista
    int priorita; //priorità di inserimento (1, in testa; 0, in coda)
};
La priorità serve solo per indicare quale file deve essere inserito in testa o in coda e per evidenziarlo con (*) nell'output della classe.
Io, in un esercizio di esame ho provato a fare una funzione void mettiInEvidenza(const char* foto), in questa maniera, da una sola classe, chiamata Timeline(la cui definizione nell'header file):
 
 void Timeline::mettiInEvidenza(const char * foto) {
        if (foto == NULL || strlen(foto) < 1)
            return;

        // scorrimento della lista fino a che non si trova l'elemento, se esiste
        Foto * p = testa; //testa è nel private della classe mettiInEvidenza ed è stata già inizializzata e ha fatto tutti gli inserimenti correttamente.
        Foto * q = p;
        while (p != NULL)
        {
            if (strcmp(p->file, foto) == 0)
            {
                if (p->priorita) // se gia' in evidenza, non si deve far niente
                    return;

                // se e' gia' il primo della lista, basta impostare priorità = 1
                if (p == testa)
                {
                    p->priorita = 1;
                    return;
                }

                // creazione di una copia dell'elemento
                Foto * r = new Foto;
                r->file = new char[strlen(p->file)+1];
                strcpy(r->file, p->file);
                r->priorita = 1;

                // inserimento in testa
                r->pun = testa;
                testa = r;

                // eliminazione vecchia copia dell'elemento
                q->pun = p->pun;
                delete[] p->file;
                delete p;
            }
            else
            {
                q = p;
                p = p->pun;
            }
        }
}

[code/]

Quello che succede, secondo il debugger, è che i puntatori delle liste iniziano ad essere infinite.
L'idea sarebbe quella di scambiare di posto un certo file che deve avere priorità 0, per essere messo in testa e convertire la priorità da 0 a 1. Se è presente, ma già in testa con priorità 0, di mettere 1, oppure lasciarlo invariato, se ha priorità 1 ed è in testa. 
Essendo che questo esercizio è fuori dallo standard, cioè richiede strumenti che ho imparato nel corso di programmazione di 1° livello di c++, ma la cui risoluzione richiede di essere improvvisata e trovata. Quindi mi stavo chiedendo come ovviare al problema della memoria della lista e fare quello richiesto, mentre non posso usare librerie per le liste.

8 Risposte

  • Re: Liste: spostare un elemento di una lista in coda o in testa.

    Già la seconda riga soffre di possibile problema di compilazione con ottimizzazione
  • Re: Liste: spostare un elemento di una lista in coda o in testa.

    +m2+ ha scritto:


    Già la seconda riga soffre di possibile problema di compilazione con ottimizzazione
    Non mi da nessun problema di compilazione e neanche Segmentation fault.
    Ho semplicemente già spiegato cosa succede, secondo Debugger.
    Essendo di primo livello, sono concentrato a far funzionare il programma e capire come mai il pun non finisce mai, cioè non arrriva mai al punto in cui il puntatore p ha puntatore a null pointer(e sì non sono abituato a ragionare secondo efficienza e secondo ricorsioni). All'inizio farebbe anche quello che avevo pensato, ma il problema principale, credo che sia l'aggiornamento dell'indirizzo pun nel codice.
    Avevo anche fatto prima di questo codice, un altro che non riusciva a cercare la lista in fondo, ma che non creava alcun problema di Segmentation fault o di compilazione.
    Sì, so che alcuni riescono a programmare usando altre funzioni della classe, ma ho fatto solo le funzioni più importanti della programmazione e quindi alcune comode funzionalità devo supporre di non conoscerle.
  • Re: Liste: spostare un elemento di una lista in coda o in testa.

    If (foto == NULL || strlen(foto) < 1)
  • Re: Liste: spostare un elemento di una lista in coda o in testa.

    Ma perché non usate il C++11 che ve la cavate in due righe, invece di impazzire...
    
    #include <algorithm>
    #include <iostream>
    #include <string> 
    #include <vector> 
    
    using namespace std;
    
    struct foto{
        string nome_file;
        int priorita;
    };
    
    class myAlbum{
    
    public:
        void inserisci_in_testa(string s, int p){
          album.insert(album.begin(), {s, p});        
        }    
        void inserisci_in_coda(string s, int p){
          album.push_back({s, p});        
        }
        void ordina_per_priorita() {
            sort (album.begin(), album.end(), [ ] (foto i, foto j) { return i.priorita > j.priorita; });
        }
        void ordina_per_nome() {
            sort (album.begin(), album.end(), [ ] (foto i, foto j) { return i.nome_file < j.nome_file; });
        }    
        void stampa(){
            for (auto it = album.begin(); it != album.end(); it++)
                cout << "File: " << (*it).nome_file << " Priorita': " << (*it).priorita << endl;
            cout << endl;   
        } 
    private:
        vector<foto>album; 
    };
    
    int main (void) {
        myAlbum test;
        
        test.inserisci_in_coda("foto01.jpg", 0);
        test.inserisci_in_coda("foto02.jpg", 1);
        test.inserisci_in_coda("foto03.jpg", 0);
        test.inserisci_in_coda("foto04.jpg", 0);
        test.inserisci_in_coda("foto05.jpg", 1);
        test.inserisci_in_coda("foto06.jpg", 1);
        test.inserisci_in_coda("foto07.jpg", 0);
        test.inserisci_in_coda("foto08.jpg", 1); 
        
        test.inserisci_in_testa("foto00.jpg", 1); 
    
        test.stampa();
        
        test.ordina_per_priorita();    
        test.stampa(); 
        
        test.ordina_per_nome();    
        test.stampa();      
    
        return 0;
    }
    
  • Re: Liste: spostare un elemento di una lista in coda o in testa.

    Allora, ora ti spiego una cosa. È colpa mia che io non abbia detto che non posso usare le librerie per la lista e per il Vector (viene chiesto esplicitamente all'esame, quindi devo fare tutto manualmente).
    Nell'esame poi chiede di usare delle determinati funzioni in public con un main fatto da loro(quindi tante cose fighe che fai con delle semplici chiamate non si possono fare, almeno che si faccia qualche funzione esterna di utilità).
    Questa roba è previsto in un altro corso a parte(strutture e algoritmi, appunto).
    Purtroppo mi trovo a volte esercizi che non so fare, perché devo usare i cicli e posso usare solo iostream, cstring, per fare cose "artigianalmente".
    Quindi vector e list non li posso usare. Non ho la minima idea di cosa faccia la libreria algoritm(se hai/ha la pazienza di spiegarmelo, sarei felice di apprenderne la sua funzionalità)
    Questa soluzione me lo terrò per gli anni a venire...
    Quindi, scusami(o mi scusi) per averti(/le) fatto sprecare tempo in questo modo.
    E quella condizione dell'if serve per gestire eventuali punti di errore: anche perché, chi dovrebbe inserire nel main una stringa vuota o stringa con meno di un carattere?
  • Re: Liste: spostare un elemento di una lista in coda o in testa.

    Banalita':

    SE il problema e' MUOVERE un certo nodo di una LISTA SEMPLICEMENTE LINKATA (perche' la descrizione del problema, benche' scritta in Italiano, e' incomprensibile!)

    1) in testa OPPURE
    2) in coda

    NON TI SERVE creare una copia della struttura dati
    BASTA correggere i puntatori dei nodi.

    A) ricerca del nodo e mantenimento di DUE puntatori, quello del nodo cercato e quello del nodo PRECEDENTE.
    Informazioni NECCESARIE perche' la lista e' di tipo semplice. Ci sono N-mila varianti molto piu' efficienti (visto che parli di efficienza)
    B) RIMOZIONE del nodo dalla sua posizione, operazione che si fa CORREGGENDO il puntatore del nodo PRECEDENTE che NON DEVE puntare al nodo trovato MA al nodo SUCCESIVO
    C) INSERIMENTO del nodo NELLA POSIZIONE CORRETTA,

    Operazione FONDAMENTALE: tutti i puntatori di TUTTI i nodi DEVONO essere opportunamente INIZIALIZZATI.

    Quindi devi tenere in consideazione

    x) se la lista contiene 0,1,2 o piu' elementi
    y) se il nodo lo posizioni IN TESTA o IN CODA

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

    Per come lo hai usato, 'priorita' NONTI SERVE A NULLA.
    Anzi, fa solo ""rumore di fondo"" e DISTOGLIE l'attenzione dal problema FONDAMENTALE.

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

    CANCELLA dalla ""testolina"" il concetto ""non ho la minima idea di che cosa faccia XXX perche' non me lo hanno insegnato"".
    SE hai un cervello e SE hai un collegamento ad Internet (e ce l'hai perche' stai scrivendo su un forum)
    ESISTONO Google, Wikipedia, siti specializzati sulle librerie del C++.

    BASTA cercare ed informarsi

    SE pensi che l'universita' ti possa insegnare tutto, sbagli di grosso. La quantita di cose che l'univ non insegna e' STRATOSFERICO.
    Compito dell'univ NON E' insegnarti TUTTO,
    MA darti gli strumenti per IMPARARE TUTTO!
  • Re: Liste: spostare un elemento di una lista in coda o in testa.

    Grazie per i suggerimenti.
    Ho risolto, pensando all'errore che avevo commesso nel primo codice che avevo elaborato(non quello che ho mandato qui, che è il secondo, il cui errore risulta essere interessante, visto che non ho ancora compreso come mai tutte le informazioni vengono perse, creando un numero infinito di liste puntate).
    Grazie al tuo consiglio sono riuscito a risolvere il problema in maniera anche relativamente ottimale.
    Comunque, ho solo chiesto un'informazione in più, visto che non ho mai incontrato tale libreria, avevo semplicemente chiesto a che cosa servisse. Visto che i forum dovrebbero essere fatti apposta per imparare e discutere, ho approfittato dell'opportunità per sapere di più(che c'è di male in questo?). Se qui nessuno vuole dare una risposta, andrò a cercare da altre parti riguardo all'argomento, non andrò a piagnucolare o a rifiutarmi di capire un meccanismo nuovo che non ho ancora compreso, perché all'università si imparano un sacco di cose, ma il sapere umano è sempre così vasto che alcuni anni non sono sufficienti per imparare tutto.
    Io ringrazio anche chi mi ha dato un codice alternativo, basato su quello che dovrebbe essere più vicino al "vero programmare"(passami il termine).
    Ho criticato solo il fatto che non potevo sfruttare la soluzione nel modo indicato, in quanto devo rispettare la consegna, non quanto una chiusura mentale ed un rifiuto ad un modo di programmare, il cui modo risulta essere più "primitivo".
    Se non sapessi tutto, non sarei venuto qui a fare delle domande.
  • Re: Liste: spostare un elemento di una lista in coda o in testa.

    Bene che hai risolto.

    <algorithm> è per la funzione sort: ignorala per il momento, tanto ti farai tutti gli algoritmi di ordinamento a mano in un altro esame.

    Se vogliono insegnarvi a fare le linked list versione "bare metal", allora secondo me la modalità corretta sarebbe scriverle come lo faresti in C, non in C++. Ci sono molti esempi delle operazioni di base anche sul forum. Sempre a mio avviso, sarebbe ora di insegnare il C++ in maniera moderna, che poi uscite dall'università dicendo che è un linguaggio orribile (lo è per certi versi, ma non è messo così male).

    ... ma comunque comandano i professori, quindi fai pure quello che devi
Devi accedere o registrarti per scrivere nel forum
8 risposte