Angenommen, wir haben die Funktion f
, die eine Ganzzahl annimmt und einen monoton ansteigenden Wert zurückgibt. Wir wollen minimal x
so finden, dass f(x) >= C
. Der Einfachheit halber sagen wir, dass die Antwort im Bereich [l;r)
liegt. Offensichtlich können wir unsere eigene Implementierung der binären Suche schreiben, aber wir wollen die existierende verwenden (std::patition_point
).Ist es möglich, standardkonforme Direktzugriffs (oder zumindest Vorwärts-) Integer-Iteratoren zu schreiben?
So naive Implementierung, wird (wahrscheinlich) Arbeit:
// f;
std::vector<int> v(r - l);
std::iota(v.begin(), v.end(), l);
answer = l + partition_point(v.begin(), v.end(), [&](int x) {
return f(x) <= C;
}) - v.begin();
Das offensichtliche Problem ist, dass wir alle Zahlen speichern haben, die viel Speicher braucht und nimmt auch Zeit, um das Array zu füllen
nächste logische Idee ist integer zu Iteratoren auf diese Weise wickeln:
struct IntIterator: std::iterator<std::random_access_iterator_tag, int> {
int current;
IntIterator(int i) : current(i) {}
int operator*() const { return current; }
IntIterator& operator++() { ++current; return *this; }
IntIterator& operator+=(size_t n) { current += (int)n; return *this; }
IntIterator operator+(size_t n) const { return current+(int)n; }
size_t operator-(IntIterator that) const { return size_t(current - that.current); }
// others operators to conform
};
answer = partition_point(IntIterator{l}, IntIterator{r}, [&](int x) {
return f(x) <= C;
});
Dies wird mit meinem Compiler (Standardbibliothek) arbeitet, ist aber nicht rand konform om Zugriff Iterator, weil
- Operator * sollte
std::iterator_traits<IntIterator>::reference
zurückgeben. wenn wir
std::iterator_traits<IntIterator>::reference
ändern (zB durch Template-Parameter zustd::iterator
Ändern) in int es wird nicht Anforderung von vorn Iterator erfüllen:wenn X ein veränderliches Iterator ist,
reference
ist ein Verweis auf T; wenn X ein const iterator ist,reference
ist eine Referenz T const,wenn wir Rückgabetyp
operator*
-[const ]T&
ändern wird es scheitern weitere Forderung der Vorwärts Iterator zu erfüllenWenn ein und b sind beide dereferenzierbar, dann
a == b
wenn und nur wenn*a
und*b
an das gleiche Objekt gebunden sind.
So verstehe ich nicht, wie man es machen konforme und Frage stellen, ob es möglich ist.
Was meinen Sie damit, dass die naive Implementierung wahrscheinlich funktionieren wird? Hast du es nicht probiert? –
Ich kann mir einen Weg vorstellen, alle Punkte hier zu adressieren, nur dass die Lebensdauer der von 'operator *' zurückgegebenen Referenz an die Lebensdauer aller Iteratoren gebunden ist, die sich mit dem dereferenzierten Iterator vergleichen. I.e. Wenn der Iterator, der dereferenziert wird, der einzige Iterator für diesen Wert ist, dann, wenn der Iterator selbst den Gültigkeitsbereich verlässt oder wenn er geändert (inkrementiert, dekrementiert) wird, ist der zuvor zurückgegebene Verweis nicht länger gültig. Überprüfen Sie nicht, ob dies die Anforderungen für einen Direktzugriffs-Iterator verletzen würde. –
@VeniVidiVici es bedeutet, es wird funktionieren, wenn ich keine Tippfehler gemacht – RiaD