Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Wahl des Containers

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
06.04.2010, 18:23 Uhr
rickie



Hallo,

ich stehe vor folgender Problemstellung:

In einem Behälter befinden sich viele Teilchen (z.B. 100000) die umher schwirren. Der Algorithmus erfordert dass die Teilchen jeweils nur um die kleinste Kollisionszeit weiterbewegt werden.
Aufgrund der vielen Teilchen im System dauert die Kollisionszeitberechnung sehr lange. Um den Algorithmus zu beschleunigen sollten deshalb die nächsten z.B. 100 Kollisionszeiten mit den jeweiligen Pointern auf die kollidierenden Teilchen gespeichert werden.

Welche Containerart ist am besten dazu geeignet die Liste mit Kollisionszeiten und den dazugehörenden Pointern auf die Teilchen zu erstellen? Wie lassen sich dabei die Zeiten geordnet eintragen ohne mit den Pointern durcheinander zu kommen?

Vielen Dank
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
06.04.2010, 18:37 Uhr
0xdeadbeef
Gott
(Operator)


So spontan würde ich sagen, das klingt nach std::queue. Es ist aber schwer zu sagen, ohne Details des Algorithmus zu kennen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
06.04.2010, 18:54 Uhr
rickie



Danke für die rasche Antwort.

Es geht nur darum, die kleinsten 100 Kollisionszeiten samt den dazugehörenden Pointern zu speichern, damit ich sie der Reihe nach auslesen kann.

Z.B: Es wurden 100000 Kollisionszeiten t berechnet. Davon sollen die 100 kleinsten t sortiert gespeichert werden, um sie der Reihe nach (beginnend mit der kleinsten Zeit) wieder auslesen zu können.

t1 (ptrTeilchen_x, ptrTeilchen_h)
t2 (ptrTeilchen_b, ptrTeilchen_n)
t3 (ptrTeilchen_h, ptrTeilchen_z)
t4 (ptrTeilchen_j, ptrTeilchen_d)
....
t100 (ptrTeilchen_r, ptrTeilchen_t)

mit t1 < t2 < t3 < t4 < ... < t100 (< als alle anderen Kollisionszeiten)

Mit welchem Container kann ich am schnellsten die 100 kleinsten Zeiten ermitteln und sortieren (umspeichern, damit die Reihenfolge stimmt; größere Zeiten verwerfen und kleinere Zeiten, wenn möglich an der richtigen Stelle zwischen 2 Zeiten einfügen)und wie handhabe ich die Pointer, damit diese nach dem Sortieren noch immer mit der richtigen Zeit korrelieren?

Dieser Post wurde am 06.04.2010 um 18:56 Uhr von rickie editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
07.04.2010, 22:45 Uhr
0xdeadbeef
Gott
(Operator)


Wenn ich das richtig verstehe, drängt sich std::priority_queue dabei auf. Es handelt sich dabei um einen Container-Adapter, der auf einem angegebenen Container (Vorgabe std::vector) einen Heap aufbaut und die Elemente praktisch on the fly sortiert. Vom Interface her läuft es darauf hinaus, dass man schnell auf das nach der angegebenen Ordnung (Vorgabe std::less<T>) größte Element zugreifen kann, während neue Elemente in logarithmischer Zeit eingefügt werden können. Laufzeitkomplexitätstechnisch kann ich dir nichts besseres bieten, wobei die Auswahl des benutzten Containers eine gewisse Rolle spielt - std::vector ist für deinen Fall wahrscheinlich keine wirklich gute Wahl, ich würde also mit std::deque experimentieren.

Wenn du die kleinsten Elemente zuerst haben willst, ist std::greater als Ordnung dein Freund, siehe unten.

Ich habe mal ein kleines Beispielprogramm / Benchmark zusammengeschrieben, um die Verwendung zu verdeutlichen:

C++:
#include <cstddef>
#include <cstdlib>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <queue>
#include <stdexcept>
#include <vector>

template<typename queue_t>
void check_queue(queue_t &q) {
  typedef typename queue_t::value_type val_t;

  val_t i = std::numeric_limits<val_t>::min();
  while(!q.empty()) {
    if(i > q.top()) {
      throw std::logic_error("Falsche Sortierung");
    }
    i = q.top();
    q.pop();
  }
}

int main() {
  unsigned long const NUM_ELEMENTS = 1000000;

  std::srand(std::time(0));

  std::clock_t bench[4];

  bench[0] = clock();

  {
    std::priority_queue<int, std::deque<int>, std::greater<int> > q;

    for(std::size_t i = 0; i < NUM_ELEMENTS; ++i) {
      q.push(rand());
    }

    check_queue(q);
  }

  bench[1] = clock();

  {
    std::priority_queue<int, std::vector<int>, std::greater<int> > q;

    for(std::size_t i = 0; i < NUM_ELEMENTS; ++i) {
      q.push(rand());
    }

    check_queue(q);
  }

  bench[2] = clock();

  {
    std::vector<int> v;
    v.reserve(NUM_ELEMENTS);

    for(std::size_t i = 0; i < NUM_ELEMENTS; ++i) {
      v.push_back(rand());
    }

    std::priority_queue<int, std::vector<int>, std::greater<int> >
      q(std::greater<int>(), v);

    check_queue(q);
  }

  bench[3] = clock();

  std::cout << bench[1] - bench[0] << std::endl
            << bench[2] - bench[1] << std::endl
            << bench[3] - bench[2] << std::endl;
}


Bei mir (g++ 4.4.3) ist die std::deque-Variante deutlich schneller als die std::vector-Variante, was vermutlich damit zusammenhängt, dass der vector in der priority_queue alle Nase lang vergrößert werden muss. Die dritte Variante mit vorher vollständig bekannten Elementen nimmt sich damit nicht all zu viel.

In deinem use case wirst du die Kollisionen in structs verpacken und eine geeignete Ordnung angeben müssen. Denkbar wäre etwa

C++:
struct kollision {
  double zeit;
  partikel p1, p2;
};

struct zeitordnung {
  bool operator()(kollision const &lhs, kollision const &rhs) const {
    return lhs.zeit > rhs.zeit;
  }
};

// ...

std::priority_queue<kollision, std::deque<kollision>, zeitordnung> q;



Bearbeitung von 0xdeadbeef:

Codebeispiel etwas aufgeräumt, Compilerreferenz eingefügt.


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 07.04.2010 um 23:42 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
08.04.2010, 08:29 Uhr
rickie



Vielen Dank für die ausführliche Hilfe!!! Ich werde es gleich einmal pobieren!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: