Domanda

Senza dubbio alcuni di voi hanno visto i miei post recenti, tutti riguardanti lo stesso programma.Continuo a riscontrare problemi con esso.Reiterare:sto ancora imparando, non sono molto avanzato, non capisco molto bene i puntatori, non frequento un corso, non capisco affatto i concetti di OOP, ecc.Questo codice unisce semplicemente due vettori ordinati, farray e sarray, in un unico vettore ordinato.Almeno spero che sia quello che fa.Dimmi:

    //int num is to find the size of the original vector and
    //build up farray and sarray; not used in the merge process
    int num = original.size() 
    std::vector<int> final;

    std::vector<int>::iterator it = farray.begin();
    std::vector<int>::iterator iter = sarray.begin();

    //farray.size() == (0 thru (num / 2))
    //sarray.size() == ((num / 2) thru num)
    for (;it != farray.end() && iter != sarray.end();) {
        if (*it > *iter) {
            final.push_back(*it);
            it++;
        }    
        else
        {
            final.push_back(*iter);
            iter++;
        }

            if (it == farray.end()) {
                for (int i = 0; iter < sarray.end(); i++) {
                    final.push_back(*iter);
                }
            }

            if (iter == sarray.end()) {
                for (int i = 0; it < farray.end(); i++) {
                    final.push_back(*iter);
                }
            }
        }

Ho riscritto la parte di unione della mia funzione di ordinamento di unione in modo da... beh, farla funzionare.In realtà ho diverse domande su questo codice:

  1. È una buona forma confrontare con std::vettore::iteratori it && iter per le mie ultime due istruzioni if ​​se il ciclo for potrebbe cambiarle al passaggio successivo?
  2. I valori di iter cambieranno nell'ultimo passaggio di questo ciclo e rovineranno il mio codice?Metterò la mia ultima istruzione if prima del confronto *it e *iter?
  3. La funzione membro end() si riferisce all'ultimo valore di qualunque cosa lo chiami?Sembra che in qualche modo potrebbe estendersi oltre.

MODIFICARE:Risponderò a tutte le risposte domani, quindi ricontrolla se vuoi saperne di più.È mezzanotte passata.Buonanotte.

È stato utile?

Soluzione

1 .Va bene confrontare gli iteratori che provengono dallo stesso contenitore di una condizione del ciclo for, ma questo ha senso solo se stai spostando uno o altri iteratori nella parte di incremento dell'istruzione del ciclo for o nel corpo del ciclo for stesso.In questo ciclo for confronti iter contro sarray.end() ma il ciclo for non cambia mai iter.Ciò significa che non ci saranno iterazioni oppure il ciclo for non terminerà mai.Inoltre, probabilmente vorrai utilizzare != e non < per il confronto. == E != funziona per tutti gli iteratori, < no.

            for (int i = 0; iter != sarray.end(); i++) {
                final.push_back(*iter);
            }

COME iter inizia dove vuoi che inizi il ciclo, potresti volere qualcosa del genere:

            for (; iter != sarray.end(); ++iter) {
                final.push_back(*iter);
            }

Dato che stai ancora imparando (anche se non lo facciamo tutti!), è probabilmente istruttivo lavorare con un algoritmo come questo, ma dovresti essere consapevole di std::merge che probabilmente fa quello che vuoi.

std::merge( farray.begin(), farray.end(), sarray.begin(), sarray.end(), std::back_inserter( final ) );

(Devi #include <iterator> E <algorithm>.)

2 .Non vedo l'incremento dell'iter o nel ciclo for esterno che invalida la logica nei cicli for successivi, il punto in 1.a parte.

3 . end() punta a uno oltre la fine di un contenitore, quindi puoi usarlo per i controlli di terminazione del ciclo, ma non dovresti provare a dereferenziare un iteratore che è "==" A ".end()".

Altri suggerimenti

Non ho controllato l'implementazione del tuo algoritmo, mi limiterò a fare riferimento alle tue tre domande:

  1. Gli iteratori sono molto simili ai puntatori ai valori di un contenitore.È esattamente come usare size_t i e poi ++i nel ciclo for.ritieni che sia problematico confrontare farray[i] con sarray[i]?probabilmente no, quindi va bene.
  2. Quello che ti vedo fare nel tuo codice qui, è che leggi semplicemente i valori di *it e *iter, in realtà non li cambi, quindi non cambieranno.
  3. La fine() punta a un luogo non valido.Non punta all'ultimo valore, ma a "dopo".È come "NULL" se vuoi, quindi se (iter == sarray.end()) è vero, andrai in crash se scriverai *iter, perché non puoi dereferenziare un iteratore che è uguale a end().

Alcuni consigli generali:Devi pensare ai nomi delle variabili.Chiamare i tuoi iteratori "it" e "iter" ad un certo punto ti confonderà.In realtà, se guardi da vicino, lo è già.Se 'farray' e 'sarray' sono nomi significativi, che ne dici di 'fiter' e 'siter'.

Inoltre, pensa a cosa sta facendo l'ordinamento di unione.Questi ultimi due blocchi sono lì solo per "drenare" qualunque iteratore abbia qualcosa rimasto.Quindi non è necessario che siano nel primo ciclo.

Probabilmente lo scriverei come (pseudocodice):

while not (list1.empty and list2.empty):
    if list1.empty:
        result.push(list2.pop)
    else if list2.empty:
        result.push(list1.pop)
    else if list1.top > list2.top:
        result.push(list2.pop)
    else:
        result.push(list1.pop)

O in C++ un po' arrugginito, culto del carico:

std::vector<int>::iterator fiter = farray.begin();
std::vector<int>::iterator siter = sarray.begin();

while (fiter != farray.end() || siter != sarray.end()) {
    if (fiter == farray.end())      final.push_back(*siter++);
    else if (siter == sarray.end()) final.push_back(*fiter++);
    else if (*fiter > *siter)       final.push_back(*siter++);
    else                            final.push_back(*siter++);
}

Hai alcune cose a cui pensare qui.

Innanzitutto, se stai unendo due intervalli, sarebbe molto meglio utilizzare il file std::unisci funzione piuttosto che rotolare il tuo.

Il tuo codice è un po' difficile da leggere perché usi stili diversi per il rientro e per la posizione delle parentesi graffe.Scegli uno stile e attieniti ad esso.

La prima parte del tuo ciclo for sembra essere un'implementazione corretta di un'unione:

for (;it != farray.end() && iter != sarray.end();) {
    if (*it > *iter) {
        final.push_back(*it);
        it++;
    }    
    else
    {
        final.push_back(*iter);
        iter++;
    }

...e questo dovrebbe essere tutto ciò che ti serve per portare a termine il lavoro.

La seconda parte del tuo ciclo presenta un paio di problemi:

   for (;it != farray.end() && iter != sarray.end();) {
         :   :
            if (it == farray.end()) {
                for (int i = 0; iter < sarray.end(); i++) {
                    final.push_back(*iter);
                }
            }

            if (iter == sarray.end()) {
                for (int i = 0; it < farray.end(); i++) {
                    final.push_back(*iter);
                }
            }
        }

Per prima cosa, i condizionali for() sono scritti in modo che entrambi it E iter non deve indicare il end() della rispettiva collezione, altrimenti il ​​ciclo finisce.COSÌ it non potrà mai indicare sarray.end(), iter non potrà mai indicare farray.end(), e nessuno dei due if l'istruzione non potrà mai essere attivata.Sono entrambi codici morti (irraggiungibili).

Ma anche se non fossero codici morti, contengono dei bug.Il condizionale in for(...) interrompe il ciclo quando l'iteratore punta alla fine della raccolta, ma questo iteratore non viene mai spostato, quindi hai un ciclo infinito.

Ancora una volta entrambi for(...)s sono codici morti non necessari perché gli iteratori non possono mai puntare alla fine del vettore.

Un semplice commento:perché non usarlo while (condition) invece di for(; !condition; ).

Quest'ultima costruzione non è standard e difficile da capire!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top