Sortieralgorithmus BubbleSort
-
EOutOfResources schrieb:
Du meine Güte! Wer hat den Code geschrieben?
Wenn du den BubbleSort meinst -> unser Prof, ziemlich fähiger Mann, auch wenn er manchmal etwas.. kompliziert wird
Die main() ist nur ein lala-Code zum Testen.
-
//Warum funktioniert an dieser Stelle folgender Aufruf nicht?..
//bubbleSort(&field.begin(), &field.end()) -> Compiler meckertErstens ist "Compiler meckert" eine sehr präzise Fehlerbeschreibung. Und zweitens liefern begin() und end() Iteratoren in deinen vector<>, das ist eine Verallgemeinerung von Pointern - und davon die Adresse zu bilden ist weder sinnvoll noch notwendig (wenn es überhaupt erlaubt ist).
PS: Wenn du schon mit STL-Containern arbeitest, dann bau deine Funktionen auch so, daß sie Iteratoren darauf entgegennehmen.
-
Sorex schrieb:
ziemlich fähiger Mann
Er soll euch lieber Iteratoren lehren statt einen
std::vector
zu nutzen und dann mit rohen Zeigern herumzuhantieren. Und eine Tauschfunktion gibt es auch schon:std::swap
-
[quote="CStoll"]
PS: Wenn du schon mit STL-Containern arbeitest, dann bau deine Funktionen auch so, daß sie Iteratoren darauf entgegennehmen.
Wie gesagt, ist nicht meine Funktion, sondern aus dem Skript.
Kriege diese Fehlermeldung, wenn ich's so mache wie gefragt:
'bubbleSort': Konvertierung des Parameters 1 von 'std::_Vector_iterator<_Myvec> *' in 'int *' nicht möglich 1> with 1> [ 1> _Myvec=std::_Vector_val<int,std::allocator<int>> 1> ] 1> Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.
-
EOutOfResources schrieb:
Sorex schrieb:
ziemlich fähiger Mann
Er soll euch lieber Iteratoren lehren statt einen
std::vector
zu nutzen und dann mit rohen Zeigern herumzuhantieren. Und eine Tauschfunktion gibt es auch schon:std::swap
Iteratoren stehen erst im nächsten Semester auf dem Plan.
-
Das ist das was CStoll gesagt hat: Der Standard legt nicht fest, dass sich Iteratoren in rohe Zeiger konvertieren lassen.
-
Sorex schrieb:
Iteratoren stehen erst im nächsten Semester auf dem Plan.
Aha! Sequenzverarbeitung (in diesem Fall Sortierung) macht ihr schon aber Iteratoren nicht. Wer hat sich diesen Plan ausgedacht?
-
Wie gesagt - begin() und end() liefern Iteratoren. Die Adresse davon zu bilden ist möglicherweise zulässig (bin nicht 100% sicher), liefert aber nichts, was du als Zeiger verwenden könntest.
-
Ok, wird mir wohl erst klar, wenn ich verstehe wie Iteratoren funktionieren... ist das evtl. auch einer der Grüne, wehsalb sich der Vector mit dieser Funktion nicht richtig sortieren lässt?
-
Sorex schrieb:
wehsalb sich der Vector mit dieser Funktion nicht richtig sortieren lässt?
Jedenfalls nicht mit definiertem Verhalten. Und die Methode
end()
liefert im Normalfall sowieso keinen Iterator zurück den du durch durchiterieren eines Zeigers erhälst.
-
Ruf ihn doch einfach so auf:
bubbleSort(&vec[0], &vec[0] + vec.size());
-
Danke, aber wird so leider auch nicht richtig sortiert.
6 15 16 20 18 20 4 10 12 8 //Ausgabe unsortiert 8 20 6 15 20 16 10 12 18 4 //Ausgabe nach "Sortiervorgang"
-
Bist du dir sicher, dass das Sortierverfahren korrekt gecoded wurde?
-
Wenn ihr eh mit Pointern arbeitet, warum lasst ihr euch nicht von der C Standardbibliothek inspirieren?
http://www.c-plusplus.net/forum/288649
cooky451 schrieb:
void bsort(void *arr, size_t n, size_t s, int (*comp)(const void*, const void*)) { int tmp; char *buf = (char*)malloc(s); if (!buf) return; do { tmp = 0; for (int i = s; i < n * s; i += s) if (comp((char*)arr + i - s, (char*)arr + i) > 0) { memcpy(buf, (char*)arr + i - s, s); memcpy((char*)arr + i - s, (char*)arr + i, s); memcpy((char*)arr + i, buf, s); tmp = 1; } } while(tmp); free(buf); }
Und ansonsten, was spricht eigentlich dagegen den Vektor gleich zu übergeben?
void bsort(std::vector<int>& vec) { int tmp; do { tmp = 0; for (int i = 1; i < vec.size(); ++i) { if (vec[i - 1] > vec[i]) { tmp = vec[i - 1]; vec[i - 1] = vec[i]; vec[i] = tmp; tmp = 1; } } } while (tmp); }
(Geht bestimmt schöner mit Iteratoren :D)
-
Na ihr könntet doch gleich
std::stable_sort
aus<algorithm>
nutzen.
-
Sorex schrieb:
//Warum funktioniert an dieser Stelle folgender Aufruf nicht?.. //bubbleSort(&field.begin(), &field.end()) -> Compiler meckert
Das, was du suchst, ist
field.front()
undfield.back()
. Den unterschied zwischen diesen undbegin()
/end()
erklärt dir die C++-Referenz deines Vertrauens.Prinzipiell schließ ich mich aber meinen Vorrednern an: Schön ist das nicht.
-
Sorex schrieb:
Danke, aber wird so leider auch nicht richtig sortiert.
6 15 16 20 18 20 4 10 12 8 //Ausgabe unsortiert 8 20 6 15 20 16 10 12 18 4 //Ausgabe nach "Sortiervorgang"
Das ist kein Wunder, schließlich stellt die Zeigerversion auch keinen Bubblesort dar. Die enthaltenen Fehler sehen allerdings wie reine Tippfehler aus.
-
EOutOfResources schrieb:
Sorex schrieb:
ziemlich fähiger Mann
Er soll euch lieber Iteratoren lehren statt einen
std::vector
zu nutzen und dann mit rohen Zeigern herumzuhantieren.Freu dich doch, dass immerhin std::vector benutzt wird.
Und eine Tauschfunktion gibt es auch schon:
std::swap
Und eine Sortierfunktion gibts auch schon
Mal dran gedacht, dass man wissen sollte, wie swap funktioniert, und das Ganze ne Lehrveranstaltung ist?
-
Ich möchte an der Stelle anmerken, dass es sich bei std::swap und std::sort nicht um Funktionen, sondern um Funktionsvorlagen handelt. Deren Existenz ist es ja, die es erst nützlich macht, Iteratoren als Konzepte statt als konkrete Typen zu definieren.
@Sorex: Die Idee hinter Iteratoren ist etwas nebulös, solange man Templates (d.h. Vorlagen) noch nicht kennt. Es handelt sich bei ihnen, wie oben angemerkt, um Konzepte, was hier bedeutet, dass jeder konkrete Typ als Iterator gilt, der bestimmte Benutzungsformen erlaubt. Dabei gibt es verschiedene, ineinander geschachtelte Iteratorkonzepte. Beispielsweise ist alles ein ForwardIterator, was neben Konstruktion, Zuweisung und Vergleich mit == und != Folgendes erlaubt:
// Sei fwditer ein ForwardIterator *fwditer; ++fwditer; fwditer++; fwditer->member_des_zieltyps;
Ein BidirectionalIterator ist etwas, was zusätzlich
// Sei bditer ein BidirectionalIterator --bditer; bditer--;
erlaubt. Jeder BidirectionalIterator ist gleichzeitig ein ForwardIterator. In ähnlicher Weise ist ein RandomAccessIterator ein BidirectionalIterator, der zusätzlich die Operationen
// Seien raiter und raiter2 RandomAccessIteratoren raiter += n; raiter -= n; raiter + n; raiter - n; raiter[n]; raiter - raiter2; // Entfernung voneinander raiter < raiter2; raiter <= raiter2; raiter > raiter2; raiter >= raiter2;
erlaubt. Zeiger sind dementsprechend RandomAccessIteratoren (!).
Iteratoren werden generell als Positionsangaben benutzt. Wenn v ein std::vector<int> ist, ist v.begin() die Position des ersten Elements des Vektors und v.end() die Position direkt hinter seinem letzten. Zwei Iteratoren in den selben Container können einen Bereich beschreiben; so ist es bei vielen Standardalgorithmen der Fall. Beispielsweise bedeutet
std::vector<int> v; ... std::sort(v.begin(), v.end());
soviel wie "sortiere alles zwischen v.begin() und v.end()". Man kann auch
std::sort(v.begin() + 1, v.end() - 1);
schreiben, was soviel bedeutet wie "sortiere alles zwischen v.begin() + 1 und v.end() - 1", also alle Elemente des Vektors außer dem ersten und letzten.
Dass das unabhängig davon möglich ist, welcher konkrete (RandomAccess)Iteratortyp benutzt wird (also dass es sowohl mit std::vector<int>::iterator als auch mit std::list<double>::reverse_iterator als auch mit int* usw. geht), liegt daran, dass es sich bei std::sort nicht um eine Funktion handelt, die einen konkreten Iteratortyp erwartet, sondern um eine Funktionsvorlage, aus der für jeden konkreten Iteratortyp, mit dem du sie benutzt, eine Funktion erstellt wird. Das ist aber ein sehr weitläufiges Thema, das ich nicht in ein paar Minuten erklären kann.
-
seldon schrieb:
Die Idee hinter Iteratoren ist etwas nebulös, solange man Templates (d.h. Vorlagen) noch nicht kennt.
Eigentlich hat das Konzept hinter Iteratoren nichts mit Templates zu tun.