Begründung für std :: lower_bound und std :: upper_bound?
STL bietet binäre Suche-Funktionen std::lower_bound und std::upper_bound
aber ich Neige dazu, Sie nicht zu verwenden, weil ich habe nicht in der Lage zu erinnern, was Sie tun,
weil Ihre Verträge scheinen völlig rätselhaft zu mir.
Nur aus der Betrachtung der Namen,
Ich würde vermuten, dass "lower_bound" könnte kurz sein für "Letzte untere Schranke",
d.h. das Letzte element in der sortierten Liste, die <= die angegebenen val (falls vorhanden).
Und ähnlich Schätze ich "upper_bound" kann auch kurz für "erste Obere Schranke",
d.h. das erste element in der sortierten Liste, ist >= die angegebenen val (wenn überhaupt).
Aber die Dokumentation sagt, Sie tun etwas anders,--
etwas, das scheint zu sein, eine Mischung von rückwärts und zufällige, zu mir.
Um die Worte des doc:
- lower_bound findet das erste element, dass s >= val
- upper_bound findet das erste element, dass s > val
So lower_bound nicht finden, eine untere Schranke an alle, es findet die erste oberen gebunden!?
Und upper_bound findet die erste strenge oberen gebunden.
Macht das Sinn??
Wie erinnern Sie sich daran?
InformationsquelleAutor der Frage Don Hatch | 2014-05-08
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie mehrere Elemente im Bereich [
first
,last
), dessen Wert gleich dem Wertval
Sie auf der Suche sind, dann wird der Bereich [l
,u
), woist genau die Anzahl der Elemente, die gleich
val
im Bereich [first
last
). Sol
undu
sind die "Untergrenze" und "Obergrenze" für die gleichen Bereich. Es macht Sinn, wenn Sie daran gewöhnt sind zu denken in der halb-offenen Intervalle.(Beachten Sie, dass
std::equal_range
zurück sowohl die unteren und oberen Grenze in einem paar, in einem einzigen Aufruf.)InformationsquelleAutor der Antwort Brian
Gibt einen iterator zeigt auf das erste element im Bereich [first, last), das ist nicht weniger als (also größer oder gleich) Wert.
Gibt einen iterator zeigt auf das erste element im Bereich [first, last) , ist größer als Wert.
Also durch das mischen von beiden unteren und oberen Grenze sind Sie in der Lage, genau zu beschreiben, wo Ihr Programm beginnt und wo es endet.
Ja.
Beispiel:
vorstellen, Vektor
prints: 4 4 4
http://en.cppreference.com/w/cpp/algorithm/lower_bound
http://en.cppreference.com/w/cpp/algorithm/upper_bound
InformationsquelleAutor der Antwort 4pie0
Halte die Reihenfolge
untere Schranke für die 6 ist die position des ersten 6.
Obere Grenze für die 6 ist die position des 7.
diese Positionen dienen als Allgemeine (begin, end) paar Benennung der Lauf der 6-Werte.
Beispiel:
InformationsquelleAutor der Antwort Cheers and hth. - Alf
In diesem Fall, denke ich, ein Bild sagt mehr als tausend Worte. Nehmen wir an, wir benutzen Sie, um die Suche für
2
in den folgenden Auflistungen. Die Pfeile zeigen, was Iteratoren die beiden zurückkehren würden:So, wenn Sie mehr als ein Objekt mit diesem Wert bereits vorhanden in der Sammlung,
lower_bound
geben Sie einen iterator, bezieht sich auf die erste von Ihnen, undupper_bound
geben einen iterator, bezieht sich auf den Gegenstand unmittelbar, nachdem der Letzte von Ihnen.Diese (unter anderem) macht die zurückgegebenen Iteratoren verwendbar als die
hint
parameterinsert
.Daher, wenn Sie diese als Tipp, das Element, das Sie einfügen, wird das neue erste Element mit diesem Wert ein (wenn Sie
lower_bound
) oder Letzte Element mit diesem Wert ein (wenn Sieupper_bound
). Wenn die Auflistung nicht enthalten, ein Element mit diesem Wert, der vorher, noch werden Sie einen iterator, der verwendet werden kann, wiehint
zu stecken Sie es in die richtige position in der Sammlung.Natürlich können Sie auch einfügen, ohne einen Hauch, aber mit einem Tipp erhalten Sie eine Garantie, dass der Einbau abgeschlossen mit konstanter Komplexität, vorausgesetzt, dass neues Element einfügen kann eingefügt werden, unmittelbar bevor das Element gezeigt, durch den iterator (so wie es in diesen beiden Fällen).
InformationsquelleAutor der Antwort Jerry Coffin
Nahm ich Brians Antwort, aber ich habe gerade realisiert, eine andere hilfreiche Art des Denkens über ist es, das schafft mehr Klarheit für mich, so dass ich bin das hinzufügen dieses für Referenz.
Denke, dass der zurückgegebene iterator als Hinweis, nicht auf das element *iter, aber nur vor , element, d.h. zwischendass element und dem vorherigen element in der Liste, wenn es einen gibt. Denken Sie, dass die Art und Weise, die Verträge der beiden Funktionen symmetrisch werden: lower_bound findet die position des übergangs von <val >=val und upper_bound findet die position des übergangs von <=val >val. Oder um es anders auszudrücken, lower_bound ist der Beginn der Reihe von Elementen, vergleichen, gleich val (d.h. der Bereich, std::equal_range gibt) und upper_bound ist das Ende von Ihnen.
Ich wünschte, Sie würden darüber sprechen, wie diese (oder jede andere gute Antworten gegeben) - in den docs; das würde es viel weniger verwirrend!
InformationsquelleAutor der Antwort Don Hatch
Beide Funktionen sind sehr ähnlich, dass Sie finden Sie die Einfügemarke in einer sortierten Reihenfolge, werden zur Erhaltung der Art. Wenn es keine vorhandenen Elemente in der Reihenfolge, die gleich sind den Suchbegriff, werden Sie wieder den gleichen iterator.
Werden, wenn Sie versuchen, etwas zu finden, in der Reihenfolge, verwenden Sie
lower_bound
- es wird direkt auf das element, wenn es gefunden wird.Wenn Sie das einfügen in die Sequenz, verwenden Sie
upper_bound
- es bewahrt die ursprüngliche Reihenfolge der Duplikate.InformationsquelleAutor der Antwort Mark Ransom
Gibt es bereits gute Antworten darauf, was
std::lower_bound
undstd::upper_bound
ist.Ich würde gerne Ihre Frage beantworten ', wie um Sie zu erinnern'?
Seine leicht zu verstehen/merken, wenn wir ziehen eine Analogie mit STL
begin()
undend()
Methoden eines Containers.begin()
gibt den Start-iterator für den container, währendend()
gibt der iterator die nur außerhalb des Behälters, und wir alle wissen, wie hilfreich Sie sind während der Iteration.Nun, auf einen sortierten container und gegebenen Wert
lower_bound
undupper_bound
zurück Reihe von Iteratoren für diesen Wert einfach zu iterieren (wie begin und end)Praktische Verwendung::
Neben der oben genannten Verwendung auf sortierte Liste, um die Auswahl für einen gegebenen Wert eines der besseren Anwendungen von upper_bound ist, um auf Daten zuzugreifen, die viele-zu-eins-Beziehung in einer Karte.
Betrachten Sie beispielsweise die folgende Beziehung:
1 -> a, 2 -> 3 -> a, 4 -> b, 5 -> c, 6 -> c, 7 -> c , 8 -> c, 9 -> c, 10 -> c
Den oben genannten 10-mappings eingespart werden können, wie folgt zugeordnet:
Die Werte zugegriffen werden kann durch den Ausdruck
(--map.upper_bound(val))->second
.Für Werte von T, angefangen von der niedrigsten bis 0, den Ausdruck zurück
UND
.Für Werte von T im Bereich von 1 zu 3, wird es wieder 'ein' und so weiter..
Nun, sich vorstellen, wir haben 100te von Daten die Zuordnung zu einem Wert und 100te von solchen Zuordnungen.
Dieser Ansatz reduziert die Größe der Karte und damit effizient.
InformationsquelleAutor der Antwort shainu vy
Für ein array oder einen Vektor :
std::lower_bound:
Gibt einen iterator zeigt auf das erste element in der Reihe, ist
std::upper_bound:
Gibt einen iterator zeigt auf das erste element in der Reihe, ist
weniger als Wert.(für array-oder Vektor in absteigender Reihenfolge)
mehr als Wert.(für array-oder Vektor in aufsteigender Reihenfolge)
InformationsquelleAutor der Antwort Vipul Jain
Ja. Die Frage absolut hat einen Punkt. Wenn jemand hat diese Funktionen Ihre Namen waren Sie denken nur von sortierten arrays mit sich wiederholenden Elementen. Wenn Sie ein array mit eindeutigen Elementen, "std::lower_bound()" wirkt eher wie eine Suche nach einer "oberen Grenze", es sei denn, es findet das eigentliche element.
Also das ist, was ich erinnere mich, über diese Funktionen:
Andernfalls Lesen Sie das Handbuch nach einem oder zwei Monaten seit der letzten Verwendung dieser Funktionen fast sicher, führt zu einem Fehler.
InformationsquelleAutor der Antwort Angel Sinigersky