Mit C ++ und hoffentlich der Standardbibliothek möchte ich eine Folge von Samples in aufsteigender Reihenfolge sortieren, aber ich möchte mich auch an die ursprünglichen Indizes der neuen Samples erinnern.
Zum Beispiel habe ich eine Menge, einen Vektor oder eine Matrix von Proben A : [5, 2, 1, 4, 3]
. Ich möchte diese sortieren B : [1,2,3,4,5]
, aber ich möchte mich auch an die ursprünglichen Indizes der Werte erinnern, damit ich eine andere Menge erhalten kann, die wie folgt lautet:
C : [2, 1, 4, 3, 0 ]
- die dem Index jedes Elements in 'B' im Original entspricht ' EIN'.
In Matlab können Sie beispielsweise Folgendes tun:
[a,b]=sort([5, 8, 7])
a = 5 7 8
b = 1 3 2
Kann jemand einen guten Weg sehen, dies zu tun?
for (size_t i = 0; i != idx.size(); ++i) idx[i] = i;
std::iota( idx.begin(), idx.end(), 0 );
#include <numeric>
für iota ()iota
ist der am wenigsten offensichtlich benannte Algorithmus in der gesamten C ++ - Standardbibliothek.Sie können std :: pair anstatt nur ints sortieren - das erste int sind Originaldaten, das zweite int ist der ursprüngliche Index. Geben Sie dann einen Komparator an, der nur nach dem ersten int sortiert. Beispiel:
Sortieren Sie die neue Probleminstanz mit einem Komparator wie folgt:
Das Ergebnis von std :: sort auf v_prime unter Verwendung dieses Komparators sollte sein:
Sie können die Indizes herausziehen, indem Sie den Vektor durchlaufen und von jedem std :: pair .second abrufen.
quelle
Angenommen, der gegebene Vektor ist
Erstellen Sie einen neuen Vektor
Sortieren Sie V und vergleichen Sie beim Sortieren die entsprechenden Elemente von A, anstatt die Elemente von V zu vergleichen
quelle
std::iota()
für eine elegantere Initialisierung vonmap
Ich habe eine generische Version der Indexsortierung geschrieben.
Die Verwendung entspricht der von std :: sort, außer dass ein Indexcontainer sortierte Indizes empfängt. testen:
Sie sollten 2 1 0 3 erhalten. Ersetzen Sie für Compiler ohne C ++ 0x-Unterstützung den Lamba-Ausdruck als Klassenvorlage:
und schreibe std :: sort as um
quelle
Nun
a
enthält beide sowohl unsere Werte und ihre jeweiligen Indizes in der sortierten.a[i].first = value
ami
'th.a[i].second = idx
im anfänglichen Array.quelle
Ich bin auf diese Frage gestoßen und habe herausgefunden, dass das direkte Sortieren der Iteratoren eine Möglichkeit ist, die Werte zu sortieren und die Indizes zu verfolgen. Es ist nicht erforderlich, einen zusätzlichen Container mit
pair
s von (Wert, Index) zu definieren. Dies ist hilfreich, wenn es sich bei den Werten um große Objekte handelt. Die Iteratoren bieten Zugriff auf den Wert und den Index:wie für das Verwendungsbeispiel:
Jetzt hätte beispielsweise das fünftkleinste Element im sortierten Vektor einen Wert
**idx[ 5 ]
und sein Index im ursprünglichen Vektor wäredistance( A.begin( ), *idx[ 5 ] )
oder einfach*idx[ 5 ] - A.begin( )
.quelle
Es gibt eine andere Möglichkeit, dies mithilfe einer Karte zu lösen:
Dadurch werden jedoch nicht eindeutige Elemente gelöscht. Wenn dies nicht akzeptabel ist, verwenden Sie eine Multimap:
Um die Indizes auszugeben, iterieren Sie über die Karte oder Multimap:
quelle
Schöne Lösung von @Lukasz Wiklendt! Obwohl ich in meinem Fall etwas allgemeineres brauchte, habe ich es ein wenig modifiziert:
Beispiel: Suchen Sie nach Indizes, die einen Vektor von Zeichenfolgen nach Länge sortieren, mit Ausnahme des ersten Elements, das ein Dummy ist.
Drucke:
quelle
std::multimap
Erwägen Sie die Verwendung wie von @Ulrich Eckhardt vorgeschlagen. Nur dass der Code noch einfacher gemacht werden könnte.Gegeben
In der mittleren Einfügezeit sortieren
Abrufen von Werten und Originalindizes
Der Grund, a
std::multimap
gegenüber a vorzuziehen ,std::map
besteht darin, gleiche Werte in ursprünglichen Vektoren zuzulassen. Bitte beachten Sie auch , dass im Gegensatz zustd::map
,operator[]
ist nicht definiert fürstd::multimap
.quelle
Machen Sie eine
std::pair
In-Funktion und sortieren Sie das Paar:generische Version:
ideone
quelle
Sind die Elemente im Vektor eindeutig? Wenn ja, kopieren Sie den Vektor, sortieren Sie eine der Kopien mit STL Sort. Dann können Sie herausfinden, welchen Index jedes Element im ursprünglichen Vektor hatte.
Wenn der Vektor doppelte Elemente verarbeiten soll, ist es meiner Meinung nach besser, Ihre eigene Sortierroutine zu implementieren.
quelle
Nun, meine Lösung verwendet Rückstandstechnik. Wir können die Werte unter Sortieren in den oberen 2 Bytes und den Indizes der Elemente platzieren - in den unteren 2 Bytes:
Sortieren Sie dann das Array
myints
wie gewohnt:Danach können Sie über Residuum auf die Indexe der Elemente zugreifen. Der folgende Code druckt die Indizes der Werte in aufsteigender Reihenfolge:
Natürlich funktioniert diese Technik nur für die relativ kleinen Werte im ursprünglichen Array
myints
(dh diejenigen, die in die oberen 2 Bytes von passen könnenint
). Es hat jedoch den zusätzlichen Vorteil, identische Werte von zu unterscheidenmyints
: Ihre Indizes werden in der richtigen Reihenfolge gedruckt.quelle
Wenn es möglich ist, können Sie das Positionsarray mit der Suchfunktion erstellen und dann das Array sortieren.
Oder Sie können eine Karte verwenden, in der der Schlüssel das Element ist, und die Werte eine Liste seiner Position in den kommenden Arrays (A, B und C).
Dies hängt von der späteren Verwendung dieser Arrays ab.
quelle
Für diese Art von Frage Speichern Sie die ursprünglichen Array-Daten in neuen Daten und suchen Sie dann binär das erste Element des sortierten Arrays in dem duplizierten Array. Dieser Index sollte in einem Vektor oder Array gespeichert werden.
Hier ist die Binärsuche eine Funktion, die das Array, die Größe des Arrays und das Suchelement übernimmt und die Position des gesuchten Elements zurückgibt
quelle
Es gibt viele Wege. Eine ziemlich einfache Lösung ist die Verwendung eines 2D-Vektors.
Hier ist die Ausgabe:
quelle