| Autor |
Nachricht |
Eisflamme
Mitglied
Benutzerprofil
Anmeldungsdatum: 26.06.2009
Beiträge: 1889
|
Eisflamme Mitglied
11:50:05 01.02.2012 Titel: |
Nochmal: vector vs map für Mapping |
Zitieren |
Hi,
sorry, ich weiß, die Diskussion gab es schon Mal, aber mir ist das noch immer nicht ganz klar geworden.
Die map ist ja zuweilen etwas verpöhnt, wenn es um kurze Mappings geht. Ich habe diverse Konstanten, die man mit | verschachteln kann. Jetzt möchte ich gerne diesen Flags Strings zuweisen, um sie artgerecht auf einem UI darzustellen.
Wenn ich einen vector nehme, hab ich eine worst-case Laufzeit von O(N) bzw. O(log(N)) mit binärer Suche. Bei einer map ist diese O(log(N)), richtig? Dann wäre doch eine map zumindest genau so gut und vom Zugriff eben noch einen Tick einfacher. Wieso dann nicht die map?
Tut mir nochmals Leid, aber hört auch mein danke. |
_________________ www.mihahome.de - Texte zu Englisch, Geographie sowie Präsentationen und Lesenswertes
Zuletzt bearbeitet von Eisflamme am 11:51:13 01.02.2012, insgesamt 1-mal bearbeitet |
|
 |
cooky451
Mitglied
Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 4840
|
cooky451 Mitglied
12:08:43 01.02.2012 Titel: |
|
Zitieren |
Die map ist intern ähnlich einer Liste. Das bedeutet, dass du schneller einfügen/entfernen kannst, aber beim Zugriff mehr Indirektionen und mehr Cache-Misses (vector liegt im Speicher ja am Stück) hast. |
_________________ Sie sind nicht berechtigt unrechtmäßige Kopien dieses Datenträgers zu erstellen.™
|
|
 |
Eisflamme
Mitglied
Benutzerprofil
Anmeldungsdatum: 26.06.2009
Beiträge: 1889
|
Eisflamme Mitglied
12:12:51 01.02.2012 Titel: |
|
Zitieren |
Ah gut, richtig... Also ist vector mit binärer Liste wohl mein Kandidat.
Wenn man schnell lesen will und die Einfüge/Lösch-Geschwindigkeit irrelevant ist, sollte man dann überhaupt je die map nutzen?
Ich kenn diesen Graphen für Container-Verwendung, der aber zwischen Mapping/Nicht-Mapping unterscheidet, sodass man im Mapping-Fall ja immer map oder set nehmen würde... demnach bietet er sich nicht an. Gibt es denn auch so eine schöne Container-Übersicht unter Berücksichtigung der Tatsache, dass man Mapping leicht mit vector emulieren kann? |
_________________ www.mihahome.de - Texte zu Englisch, Geographie sowie Präsentationen und Lesenswertes
Zuletzt bearbeitet von Eisflamme am 12:13:47 01.02.2012, insgesamt 1-mal bearbeitet |
|
 |
cooky451
Mitglied
Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 4840
|
cooky451 Mitglied
12:28:01 01.02.2012 Titel: |
|
Zitieren |
| Eisflamme schrieb: | | Gibt es denn auch so eine schöne Container-Übersicht unter Berücksichtigung der Tatsache, dass man Mapping leicht mit vector emulieren kann? |
Ich glaube nicht, diese Karte ist ja eher eine Orientierung für Anfänger. Selbst denken ist immer besser.
| Eisflamme schrieb: | | sollte man dann überhaupt je die map nutzen? | Ja. Wenn du eben viele Daten hast und ab und zu etwas einfügen/entfernen willst, dann ist eine Liste schneller. Oder wenn dir Performance egal ist und du das einfachere Interface möchtest. |
_________________ Sie sind nicht berechtigt unrechtmäßige Kopien dieses Datenträgers zu erstellen.™
Zuletzt bearbeitet von cooky451 am 12:28:29 01.02.2012, insgesamt 1-mal bearbeitet |
|
 |
Bashar
Mitglied
Benutzerprofil
Anmeldungsdatum: 15.05.2001
Beiträge: 16828
|
Bashar Mitglied
12:33:06 01.02.2012 Titel: |
|
Zitieren |
| cooky451 schrieb: | | und du das einfachere Interface möchtest. |
Das ist kein Hindernis, man kann sich ja eine auf sortierten Vektoren basierende map bauen. |
_________________ OSL♥
|
|
 |
cooky451
Mitglied
Benutzerprofil
Anmeldungsdatum: 16.10.2010
Beiträge: 4840
|
cooky451 Mitglied
12:44:39 01.02.2012 Titel: |
|
Zitieren |
| Bashar schrieb: |
Das ist kein Hindernis, man kann sich ja eine auf sortierten Vektoren basierende map bauen. | Ja, das meinte ich aber nicht, war schlecht formuliert; sollte heißen: "Oder wenn dir Performance egal ist und du dich nicht darum kümmern möchtest."
Der Vektor ist im jeweils schlechtesten Fall halt wesentlich langsamer. |
_________________ Sie sind nicht berechtigt unrechtmäßige Kopien dieses Datenträgers zu erstellen.™
Zuletzt bearbeitet von cooky451 am 12:45:04 01.02.2012, insgesamt 1-mal bearbeitet |
|
 |
megaweber
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.07.2006
Beiträge: 205
|
megaweber Mitglied
17:29:13 01.02.2012 Titel: |
|
Zitieren |
Vielleicht gibt es ja auch eine Möglichkeit die Flags als int's zu verwenden oder zu interpretieren, dann kannst Du mit einem vector natürlich ohne Suche auf die Elemente zugreifen... |
|
|
|
 |
Eisflamme
Mitglied
Benutzerprofil
Anmeldungsdatum: 26.06.2009
Beiträge: 1889
|
Eisflamme Mitglied
18:51:52 01.02.2012 Titel: |
|
Zitieren |
Es sind halt 32 Flags, die alle beliebig kombiniert werden können, der Vector wäre dann etwas arg groß. ^^ |
_________________ www.mihahome.de - Texte zu Englisch, Geographie sowie Präsentationen und Lesenswertes
|
|
 |
314159265358979
Mitglied
Benutzerprofil
Anmeldungsdatum: 09.03.2010
Beiträge: 4623
|
314159265358979 Mitglied
19:13:10 01.02.2012 Titel: |
|
Zitieren |
Dafür ist sowohl vector, als auch map falsch. Dafür nimmt man 2 rohe C-Arrays, die bereits entsprechend vorsotiert sind. Die Suche des Flags im ersten Array liefert dann den Index des entsprechenden Strings im zweiten. |
Zuletzt bearbeitet von 314159265358979 am 19:13:31 01.02.2012, insgesamt 1-mal bearbeitet |
|
 |
314159265358979
Mitglied
Benutzerprofil
Anmeldungsdatum: 09.03.2010
Beiträge: 4623
|
314159265358979 Mitglied
19:59:09 01.02.2012 Titel: |
|
Zitieren |
Und wer ganz flotten Lookup in O(1) haben möchte, der machts so:
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | unsigned log2(unsigned x)
{
unsigned y;
asm("bsr %1, %0" : "=r"(y) : "r"(x));
return y;
}
#define FLAG(name, value) unsigned const name = value;
FLAG(foo, 1)
FLAG(bar, 2)
FLAG(baz, 4)
FLAG(qux, 8)
// usw...
#undef FLAG
char const* const stringvals[] = { "foo", "bar", "baz", "qux" };
char const* flag_to_string(unsigned flag)
{
return stringvals[log2(flag)];
} | |
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | unsigned log2(unsigned x)
{
unsigned y;
asm("bsr %1, %0" : "=r"(y) : "r"(x));
return y;
}
#define FLAG(name, value) unsigned const name = value;
FLAG(foo, 1)
FLAG(bar, 2)
FLAG(baz, 4)
FLAG(qux, 8)
// usw...
#undef FLAG
char const* const stringvals[] = { "foo", "bar", "baz", "qux" };
char const* flag_to_string(unsigned flag)
{
return stringvals[log2(flag)];
} | |
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | unsigned log2(unsigned x)
{
unsigned y;
asm("bsr %1, %0" : "=r"(y) : "r"(x));
return y;
}
#define FLAG(name, value) unsigned const name = value;
FLAG(foo, 1)
FLAG(bar, 2)
FLAG(baz, 4)
FLAG(qux, 8)
// usw...
#undef FLAG
char const* const stringvals[] = { "foo", "bar", "baz", "qux" };
char const* flag_to_string(unsigned flag)
{
return stringvals[log2(flag)];
} | |
|
Zuletzt bearbeitet von 314159265358979 am 20:09:05 01.02.2012, insgesamt 1-mal bearbeitet |
|
 |
pumuckl
Moderator
Benutzerprofil
Anmeldungsdatum: 21.06.2005
Beiträge: 6578
|
pumuckl Moderator
19:59:21 01.02.2012 Titel: |
|
Zitieren |
| 314159265358979 schrieb: | | Dafür ist sowohl vector, als auch map falsch. Dafür nimmt man 2 rohe C-Arrays | Kommt immer drauf an.
Wenn du ein fixes mapping hast, ohne einfügen und löschen, dann reicht ein statisches C-Array mit den Schlüssel-Wert-Paaren (Wozu du da zwei Arays nehmen willst ist mir schleierhaft). Wers möchte kann das natürlich auch in ein std::array packen, aber das ist nur Syntax-Candy.
Wenn man Schlüssel-Wert-Paare einfügen/löschen möchte, braucht man entsprechend dynamische Strukturen, da sind rohe C-Arrays Blödsinn.
Allgemein wäre ich mit solchen Absolut-Aussagen "Das ist falsch, das macht man anders" immer vorsichtig. Vor allem wenn die Rahmenbedingungen nicht genau feststehen.
Zum "einfacheren Zugriff" auf maps: kann man sich für statische Tabellen auch selber schreiben |
_________________ Du brauchst Hilfe? - Kleines Einmaleins der Forenregeln.
When your hammer is C++, everything begins to look like a thumb. (Steve Haflich)
|
|
 |
314159265358979
Mitglied
Benutzerprofil
Anmeldungsdatum: 09.03.2010
Beiträge: 4623
|
314159265358979 Mitglied
20:11:01 01.02.2012 Titel: |
|
Zitieren |
Dass es Flags sind, impliziert eigentlich für mich, dass zur Laufzeit keine hinzukommen. Eine Methode mit einem einzigen Array habe ich gerade gezeigt, würde mich interessieren, wie du das gelöst hättest. |
|
|
|
 |
Eisflamme
Mitglied
Benutzerprofil
Anmeldungsdatum: 26.06.2009
Beiträge: 1889
|
Eisflamme Mitglied
12:42:42 02.02.2012 Titel: |
|
Zitieren |
Die Flags sind natürlich statisch, die Texte erstmal auch. Aber bald hab ich vor das zu internationalisieren und dann sind die natürlich nicht mehr statisch. Wobei ich noch nicht sicher bin, ob man die Sprache live umstellen können soll.
Wieso nutzt Du im Code ein Makro für die Konstantendefinition? Tipparbeit ersparen? Ansonsten geht log2 natürlich ganz gut... kann man ja sogar noch als Template implementieren. |
_________________ www.mihahome.de - Texte zu Englisch, Geographie sowie Präsentationen und Lesenswertes
|
|
 |
314159265358979
Mitglied
Benutzerprofil
Anmeldungsdatum: 09.03.2010
Beiträge: 4623
|
314159265358979 Mitglied
13:39:48 02.02.2012 Titel: |
|
Zitieren |
Schreibfaulheit
Wenn du verschiedene Sprachen hast, dürfte das ebenfalls kein Problem sein. Dann steckst du die Arrays jeder Sprache nochmal in ein Array und gibst der Funktion für die Umwandlung als Parameter den Index des äußeren Arrays mit. Etwa so:
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 | 1 2 3 4 5 6 7 8 9 10 | #define DEFCONST(name, value) unsigned const name = value; // natürlich bin ich schreibfaul ;)
DEFCONST(de, 0)
DEFCONST(en, 1)
#undef DEFCONST
char const* const stringvals[][] = { { "foo", "bar" }, { "baz", "qux" } };
char const* flag_to_string(unsigned flag, unsigned lang)
{
return stringvals[lang][log2(flag)];
} | |
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 | #define DEFCONST(name, value) unsigned const name = value; // natürlich bin ich schreibfaul ;)
DEFCONST(de, 0)
DEFCONST(en, 1)
#undef DEFCONST
char const* const stringvals[][] = { { "foo", "bar" }, { "baz", "qux" } };
char const* flag_to_string(unsigned flag, unsigned lang)
{
return stringvals[lang][log2(flag)];
} | |
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 | #define DEFCONST(name, value) unsigned const name = value; // natürlich bin ich schreibfaul ;)
DEFCONST(de, 0)
DEFCONST(en, 1)
#undef DEFCONST
char const* const stringvals[][] = { { "foo", "bar" }, { "baz", "qux" } };
char const* flag_to_string(unsigned flag, unsigned lang)
{
return stringvals[lang][log2(flag)];
} | |
Wobei, für eine Sprache kannst du auch ein enum nehmen, wie auch immer. Ich bin mir gerade allerdings nicht sicher, ob MSVC schon enum classes unterstützt.
Nebenbei sollte die Funktion log2 wohl eher log2_minus_one heißen.
Mit enum class vielleicht so:
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 | 1 2 3 4 5 6 7 8 9 10 | enum class language : unsigned
{
de = 0,
en = 1,
};
char const* flag_to_string(unsigned flag, language lang)
{
return stringvals[static_cast<unsigned>(lang)][log2(flag)];
} | |
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 | enum class language : unsigned
{
de = 0,
en = 1,
};
char const* flag_to_string(unsigned flag, language lang)
{
return stringvals[static_cast<unsigned>(lang)][log2(flag)];
} | |
| C/C++ Code: | 1 2 3 4 5 6 7 8 9 10 | enum class language : unsigned
{
de = 0,
en = 1,
};
char const* flag_to_string(unsigned flag, language lang)
{
return stringvals[static_cast<unsigned>(lang)][log2(flag)];
} | |
|
Zuletzt bearbeitet von 314159265358979 am 13:43:31 02.02.2012, insgesamt 2-mal bearbeitet |
|
 |
C++ler.
Unregistrierter
|
C++ler. Unregistrierter
14:33:03 02.02.2012 Titel: |
|
Zitieren |
Was fuer mieser C Frickelcode. |
|
|
|
 |
314159265358979
Mitglied
Benutzerprofil
Anmeldungsdatum: 09.03.2010
Beiträge: 4623
|
314159265358979 Mitglied
14:38:30 02.02.2012 Titel: |
|
Zitieren |
| C++ler. schrieb: | Was fuer mieser C Frickelcode.  |
Was für ein dummer, falscher Kommentar |
Zuletzt bearbeitet von 314159265358979 am 14:38:44 02.02.2012, insgesamt 1-mal bearbeitet |
|
 |
DerWarGut
Unregistrierter
|
DerWarGut Unregistrierter
15:36:14 02.02.2012 Titel: |
|
Zitieren |
Ein globales char* array und Makros sind also guter C++ Stil? lol |
|
|
|
 |
314159265358979
Mitglied
Benutzerprofil
Anmeldungsdatum: 09.03.2010
Beiträge: 4623
|
314159265358979 Mitglied
16:09:34 02.02.2012 Titel: |
|
Zitieren |
Ob das Array global ist oder nicht, darauf habe ich mich in meinem Code nicht festgelegt. An einem Array aus char const* ist nichts verwerflich.
Makros sind nicht grundsätzlich böse. Es ist böse, sie für Funktionen zu missbrauchen, da das zu schwer findbaren Fehlern führt. Hier machen sie den Code sogar besser, da dadurch Redundanzen und damit auch mögliche Copy & Paste-Fehler beseitigt werden. Als netter Nebeneffekt ists auch weniger Tipparbeit und der Code wird besser wartbar, da nur an einer Stelle ausgebessert werden muss. |
Zuletzt bearbeitet von 314159265358979 am 16:11:31 02.02.2012, insgesamt 1-mal bearbeitet |
|
 |
#undef π
Unregistrierter
|
#undef π Unregistrierter
19:10:35 02.02.2012 Titel: |
|
Zitieren |
| C/C++ Code: | typedef unsigned int const flag_t;
flag_t foo = 1;
flag_t bar = 2;
flag_t baz = 4;
flag_t qux = 8;
| |
| C/C++ Code: | typedef unsigned int const flag_t;
flag_t foo = 1;
flag_t bar = 2;
flag_t baz = 4;
flag_t qux = 8;
| |
| C/C++ Code: | typedef unsigned int const flag_t;
flag_t foo = 1;
flag_t bar = 2;
flag_t baz = 4;
flag_t qux = 8;
| |
|
|
|
|
 |
314159265358979
Mitglied
Benutzerprofil
Anmeldungsdatum: 09.03.2010
Beiträge: 4623
|
314159265358979 Mitglied
19:18:59 02.02.2012 Titel: |
|
Zitieren |
Das ist aber immer noch weniger gut wartbar. Ein Flag muss keine Variable sein. |
|
|
|
 |
Michael E.
Mitglied
Benutzerprofil
Anmeldungsdatum: 25.10.2003
Beiträge: 5323
|
Michael E. Mitglied
23:02:48 02.02.2012 Titel: |
|
Zitieren |
| 314159265358979 schrieb: | | Das ist aber immer noch weniger gut wartbar. Ein Flag muss keine Variable sein. |
Bitte was?
BTW: Was spricht gegen enums? |
_________________ Your password must be at least 18770 characters and cannot repeat any of your previous 30689 passwords. Please type a different password. Type a password that meets these requirements in both text boxes. (http://support.microsoft.com/kb/276304/en-us/)
Zuletzt bearbeitet von Michael E. am 23:03:43 02.02.2012, insgesamt 1-mal bearbeitet |
|
 |
314159265358979
Mitglied
Benutzerprofil
Anmeldungsdatum: 09.03.2010
Beiträge: 4623
|
314159265358979 Mitglied
23:40:58 02.02.2012 Titel: |
|
Zitieren |
| Michael E. schrieb: | | Bitte was? |
Ach, vergiss es. Sobald ich irgendwas sage, kommt bestimmt wieder gleich ein Unreg daher und versucht, wieder was falsches rauszulesen. Kein Bock mehr, meine Grundidee, wie mans mit den Arrays macht, ist rübergekommen.
| Michael E. schrieb: | | BTW: Was spricht gegen enums? |
Nichts. |
|
|
|
 |
Bashar
Mitglied
Benutzerprofil
Anmeldungsdatum: 15.05.2001
Beiträge: 16828
|
Bashar Mitglied
00:10:37 03.02.2012 Titel: |
|
Zitieren |
| 314159265358979 schrieb: | | Ach, vergiss es. Sobald ich irgendwas sage, kommt bestimmt wieder gleich ein Unreg daher und versucht, wieder was falsches rauszulesen. |
Man lernt mit der Zeit, die Deppen zu ignorieren. |
_________________ OSL♥
|
|
 |