2009-04-20 4 views
2

Ich arbeite an einer Merge-Sortierfunktion. Ich habe das Problem gelöst - ich versuche, meinen Merge-Teil fertig zu bekommen. Angenommen, ich lerne C++, habe ein kursorisches Wissen über Zeiger und verstehe nicht alle Regeln von std :: vector :: iterator (oder std :: vectors, was das betrifft).Können Sie for Schleifen (ineinander) in C++ einbetten

Angenommen, num ist die Größe des ursprünglichen std :: vectors, die Werte (std :: copy) aus einem Array der Größe "int ar [num]" kopiert hat. Angenommen, farray hat die Werte von (0 bis (num/2)) und sarray hat die Werte von ((num/2) bis num).

int num = original.size(); 
std::vector<int> final(num); 

for (std::vector<int>::iterator it = farray.begin(); it != farray.end(); ++it) { 
    for (std::vector<int>::iterator iter = sarray.begin(); iter != sarray.end(); ++iter) { 
     if (*it > *iter) final.push_back(*it); 
      else 
       final.push_back(*iter); 
    } 
} 

Dieser Code kompiliert und meine letzte stabile Version von Bloodshed Dev-C++ wirft keine Warnungen oder Fehler. Ich weiß nicht, ob das gültig ist, ich muss immer noch versuchen, alle Werte des Finales zu verbessern. Ich möchte nur wissen, ob das üblich ist, anfällig für Fehler oder einfach nur schlecht. Und wenn ja, wie würden Sie

+0

Wenn Sie immer noch versuchen, Iteratoren und ähnliches zu verstehen, könnte es nützlich sein, sie in einer vertrauten Notation zu schreiben (wie mit dem [] -Operator) und dann, sobald sie funktioniert, zu Iteratoren zu wechseln. Aber bleiben Sie nicht bei [], denn Iteratoren sind wichtig zu verstehen, besonders wenn Sie zu anderen STL-Typen wie Maps und Sets usw. kommen. – Smashery

Antwort

7

Es ist gültig ... aber eine For-Schleife ist wahrscheinlich nicht das, was Sie wollen. Wenn Sie zwei for-Schleifen verwenden, geht Ihre innere Schleife jedes Mal, wenn die äußere Schleife eine Schleife ausführt, zum Anfang zurück. Also, wenn Ihr Vektoren enthalten:

farray: 10 9 8 4 3 
sarray: 7 6 4 3 1 

Dann wird Ihre endgültige Array enthält so etwas wie:

10 10 10 10 10 9 9 9 9 9 8 8 8 8 8 7 6 4 4 4 7 6 4 3 3 

, weil man jede einzelne Kombination testen, und das Hinzufügen der größeren auf die endgültige Liste. Eine bessere Lösung könnte darin bestehen, sich für jede Liste einen Iterator zu merken und nur eine Schleife zu verwenden. Anstatt eine Liste zu durchlaufen, gehen Sie einfach beide zusammen durch - wenn sarray die größere Zahl hat, inkrementieren Sie den sarray-Iterator und vergleichen Sie ihn mit dem alten farray-Iterator. Stoppen Sie Ihre Schleife, wenn sowohl Sarray als auch Farray leer sind.

vector<int> fiter = farray.begin(); 
vector<int> siter = sarray.begin(); 
vector<int> final; 

// Let's traverse both farray and sarray. 
// We'll want to stop this loop once we've traversed both lists. 
while (fiter != farray.end() && siter != sarray.end()) 
{ 
    if (fiter == farray.end()) 
    { 
     // we must have gone right through farray - 
     // so use the value from sarray, and go to the next one 
     final.push_back(*siter); 
     siter++; 
    } 
    else if (siter == sarray.end()) 
    { 
     // we must have gone right through sarray - 
     // so use the value from farray, and go to the next one 
     final.push_back(*fiter); 
     fiter++; 
    } 
    else if (*siter > *fiter) 
    { 
     // siter is the bigger of the two - add it to the final list, and 
     // go to the next sarray entry 
     final.push_back(*siter); 
     siter++; 
    } 
    else // *fiter >= *siter 
    { 
     // fiter is the bigger of the two - add it to the final list, and 
     // go to the next farray entry 
     final.push_back(*fiter); 
     fiter++; 
    } 
} 

Ich habe es nicht getestet - und wenn dies für die Hausaufgaben, dann bitte versuchen zu verstehen, was ich getan habe, geh weg und schreibt es selbst, anstatt Kopie + Paste.

+0

Würden Sie Ihre Implementierung erklären? – jkeys

+0

Ich habe ein Beispiel (ungetested) Implementierung gegeben - es verwendet nur eine while-Schleife und geht weiter, bis es beide Listen durchlaufen hat. Wenn es eine ganze Liste durchläuft, fügt es nur die in der Liste ohne Liste hinzu. Andernfalls vergleicht es die beiden Elemente und fügt das größere hinzu, bevor der Iterator in dieser Liste inkrementiert wird. – Smashery

+0

Zusätzlich wird 'final' mit 'num'-Einträgen von 0 erzeugt, um damit zu beginnen, dann werden die echten Einträge an diese angehängt. Ich glaube nicht, dass dies das gewünschte Verhalten ist. –

1

Sie können Schleifen aller Art verschachteln (für, während, während), solange Sie die Schleife Variablen nicht wiederverwenden. Wenn Sie versuchen würden, dass es kompilieren würde, kann es während der Laufzeit kläglich scheitern. Obwohl es technisch möglich ist, den gleichen Namen für geschachtelte Schleifenvariablen in modernem C und C++ zu verwenden, ist es verwirrend und sollte vermieden werden.

Es ist nicht mehr oder weniger anfällig für Fehler als eine einzige Schleife mit Ausnahme des bereits erwähnten Problems mit der Wiederverwendung von Schleifenvariablen.

Lesen Sie mehr über die limits von verschachtelten Schleifen.

+0

Sie können Loop-Variablen in verschachtelten Schleifen wiederverwenden. Es ist normalerweise keine gute Idee, aber es bedeutet nicht automatisch, dass es zur Laufzeit abstürzt, wenn Sie vorsichtig damit sind, was Sie damit machen. – Peter

+0

Sie meinen wie int i = 0, um über beide Schleifen zu iterieren? Würden Sie es in der eingebetteten Schleife oder der äußeren Schleife erhöhen? – jkeys

+0

Das Fehlschlagen zur Laufzeit bedeutet nicht unbedingt Absturz. Es könnte einfach falsche Ergebnisse berechnen. – lothar

0

Ja, Sie können dies tun. Und ja, es ist oft anfällig für Fehler. In der Tat ist das Schreiben von Schleifen selbst anfällig für Fehler, was ein Argument dafür ist, die Algorithmen in der STL wie for_each, copy und transform zu verwenden.

+0

Haha, Ich bin nicht so weit voraus. Ich benutze tatsächlich std :: copy in diesem Programm, um die Werte aus dem ursprünglichen Array [num] zu std :: vector Original zu kopieren.Würdest du mir sagen, was der ehemalige und letzte sind? – jkeys

+0

Ich wundere mich manchmal manchmal, wer diese Idioten sind Stimmantworten wie diese sind. –

+0

Hooked: for_each() wird verwendet, um die gleiche Operation für jedes Element in einem Bereich auszuführen, wie folgt: for_each (v.begin(), v.end(), doSomething()); 'doSomething()' ist ein sogenannter Funktor, der gegen jeden Wert in 'v' ausgeführt wird. –

2

Merge Sort-Algorithmus zur Seite, für die Schleife mit Iterators verschachtelt ist ebenso gültig wie bei zwei Variablen für Schleifen verschachtelt i und j .

+0

Es war mein Verständnis, dass Iteratoren meine einzige Option waren - können Sie Ganzzahlen verwenden, um über std :: vector v zu iterieren? – jkeys

+0

Natürlich können Sie. Verwenden Sie den Operator [] genau wie ein Array oder die at() -Memberfunktion. Überprüfen Sie Ihre Lieblings-STL-Dokumentation für Details. –

+0

Iteratoren werden in diesem Fall zu Zeigern kompilieren, und nur die Verwendung der Inder [] wird sich gleich verhalten, aber ich bezog mich auf eine Art von verschachtelten Schleifen im Allgemeinen. –

0

Ja, Sie können Schleifen oder andere Anweisungen so tief verschachteln, wie Sie möchten (innerhalb des Grundes; es gibt Grenzen, wie in einer anderen Antwort erwähnt, aber sie liegen weit über dem, was Sie jemals brauchen sollten).

1

Die Verschachtelung für Schleifen ist eine absolut legitime Möglichkeit, Dinge zu tun.Zum Beispiel ist es die klassische Methode der "alten Schule", ein 2D-Array zu durchlaufen - eine Schleife verläuft entlang der y-Achse und die andere Schleife entlang der x-Achse.

Heute, mit diesen Kindern und ihre für jeden Schleifen und Iteratoren und Mapping-Funktionen gibt es wohl "besser" Möglichkeiten, es zu tun, (für einige Definition besser) aber Verschachtelung Schleifen funktioniert ganz gut. Die Verwendung von C++ oder Zeigern ändert das nicht.

Verwandte Themen