Was ist der effizienteste Weg, um eine std :: Menge von ersten n ganzen Zahlen zu schaffen?

stimmen
4

Ich versuche, einen Satz von n ganzen Zahlen in c ++ zu erstellen, und ich habe mich gefragt werde, gibt es eine effizientere Art und Weise es eher als die einfachen for-Schleife zu tun, wie unten gezeigt

 std::set<int> indices;
    for(int i = 0; i < n; ++i){
        indices.insert(i);
    }

Ich habe versucht, googeln, konnte aber die keine Antworten finden. Ich fühle mich wie die inkrementelle Natur der Zahlen eingefügt wird zu einer effizienteren Umsetzung führen soll.

Veröffentlicht am 03/12/2018 um 15:31
quelle vom benutzer
In anderen Sprachen...                            


4 antworten

stimmen
3

Wahrscheinlich nicht ein effizienter, nein.

std::generate(oder in diesem Fall mehr direkt std::iota) kann auch das tun , was Sie wollen, aber aus der Spitze von meinem Kopf kann ich nicht einen besonderen Vorteil gegenüber einer einfachen sehen forSchleife, zumindest in Bezug auf Leistung.

Letztlich wird, was Sie am Ende tun, müssen viele Baumknoten mit diesen Werten erstellen, und zu einem gewissen Grad muss der Computer wiederholen, dies zu tun. Sie erhalten keinen Nutzen aus bereits Zuteilung hier, weil dieser Begriff mit einem Satz sinnlos ist (obwohl dies ein gültiger Vorschlag für einen Vektor wäre).

(Edit: Ich kann nicht Kredit für diese nehmen, aber rodrigo weist darauf hin, dass ein Einsatz Hinweis helfen kann Anecdotally hörte ich irgendwo, dass Hinweise sind in der Regel heutzutage ignoriert werden, aber ich bin nicht sicher, wie wahr das ist..)

Der beste Weg ist , um zu versuchen , dies nicht zu wollen. Normalerweise , wenn Sie eine Sammlung von haben N aufeinanderfolgenden ganzen Zahlen, können Sie einen Weg finden , um es nicht brauchen, sei es durch einige magische Mathematik oder zumindest durch Erzeugen nur das, was Sie bei Bedarf benötigen. Ich nehme an, es eine Ausnahme , obwohl zu jeder Regel ist.

Beantwortet am 03/12/2018 um 15:34
quelle vom benutzer

stimmen
3

Es ist diese Überlastung für set::insert():

iterator insert( iterator hint, const value_type& value );

wo der Hinweis ist die Position, wo Sie den Wert denken eingefügt werden soll. Da Ihre Werte sortiert sind, können Sie tun:

for (int i = 0; i < n; ++i){
    indices.insert(indices.end(), i);
}

Und bekommt konstant fortgeführten Anschaffungs Zeit, statt logarithmischer Zeit für jeden Einsatz.

Aus der GCC - Dokumentation :

Einfügungen aus logarithmischer Komplexität verändern konstante Zeit amortisieren, wenn der Hinweis richtig verwendet wird. [...]

Wenn der Hinweis Parameter [...] entspricht: [...]

  • end (), dann wird das Element eingeführt werden, sollte einen Schlüssel größer als all anderen Tasten in dem Behälter hat.
Beantwortet am 03/12/2018 um 15:37
quelle vom benutzer

stimmen
7

Wenn Sie effizient sein wollen , können Sie nutzen emplace_hint. Wenn der Wert sollte einzulagern direkt vor dem Hinweis eingelagert wird , dann wird es in konstanter Zeit geschehen statt log N.

std::set indices;
for (int i = 0; i < n; ++i)
{
    indices.emplace_hint(indices.end(), i);
}

sollte O(N)statt O(NlogN).

Beantwortet am 03/12/2018 um 15:37
quelle vom benutzer

stimmen
1

Wenn Sie auf direkte Konstruktion festgelegt sind, und sind bereit , Boost zu verwenden, counting_iteratorist eine Alternative:

std::set<int> indices(boost::counting_iterator<int>(0), boost::counting_iterator<int>(n));
Beantwortet am 03/12/2018 um 15:38
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more