Ich ging ein wenig weiter und schrieb zwei Versionen, eine basierend auf einem Lookup-Array, die andere auf einem Set mit einem zugrunde liegenden Hash.
class CharLookup {
public:
CharLookup(const std::string & set) : lookup(*std::max_element(set.begin(), set.end()) + 1) {
for (auto c : set) lookup[c] = true;
}
inline bool has(const unsigned char c) const {
return c > lookup.size() ? false : lookup[c];
}
private:
std::vector<bool> lookup;
};
class CharSet {
public:
CharSet(const std::string & cset) {
for (auto c : cset) set.insert(c);
}
inline bool has(const unsigned char c) const {
return set.contains(c);
}
private:
QSet<unsigned char> set;
};
Dann schrieb ein kleiner Benchmark, fügte ein paar weitere Container für den Vergleich hinzu.Lower besser ist, sind die Datenpunkte für „Zeichensatz Größe/Textgröße“:
Scheint wie für kurze Zeichensätze und Text, std::string::find_first_of
ist am schnellsten, sogar schneller als eine Lookup-Array, aber schnell schwindet, wenn die Testgröße zunimmt. std::vector<bool>
scheint wie das "goldene Mittel", QBitArray
hat wahrscheinlich eine etwas andere Implementierung, weil es voranschreitet, wie die Testgröße zunimmt, beim größten Test QVector<bool>
ist am schnellsten, vermutlich, weil es nicht den Overhead von Bit-Zugriff hat. Die beiden Hash-Sets sind nahe, Handelsplätze, zuletzt und am wenigsten gibt es die std::set
.
Getestet auf einer i7-3770k Win7 x64 Box mit MinGW 4.9.1 x32 mit -O3.
Setzen Sie 'ch1'' ch2' und 'ch3' in ein' std :: unordered_set 'dann testen, ob c drin ist. es ist o (1) Zeit-Lookups. O (m) Speicher mit m = Anzahl der Zeichen in Ihrem Set. Der Rest ist nur (hässliche und dumme) vorzeitige Optimierung. Dafür steht std :: set. –
Seien Sie vorsichtig, da diese ausgefallenen Datenstrukturen dynamische Speicherzuweisungen verursachen können, die langsamer als eine normale if-Anweisung sind. –
Sie können versuchen, sie globale Variablen (zB 'statische const') in einer Funktion zu machen, um Baukosten zu sparen. –