C#のHashSet、Dictionaryに対応するのが std::set / std::unordered_set、std::map / std::unordered_mapである。
ただし、set と map はツリー構造である。これに対して unordered_set, unordered_map はハッシュ構造である。 このため、一般には、unordered_set,unordered_map の方が抽出速度が速い。
#include <iostream>
#include <unordered_set>
using namespace std;
unordered_set<int> set;
void find(int n) {
auto it = set.find(n);
if (it == set.end()) cout << n << "はありません\n";
else cout << n << "はあります\n";
}
int main() {
set.insert(34);
set.insert(55);
set.insert(93);
find(55);
find(44);
}
unordered_map<int, int> mp_even;
vector<pair<int, int> > elem_even(mp_even.begin(), mp_even.end());
sort(elem_even.begin(), elem_even.end(),
[](pair<int, int> a, pair<int, int> b) { return a.second > b.second; });
地図システムで std::unordered_set を使ってみた。関係部分の抜粋を下に示す。 レンダリング処理時間は 10ミリ秒のオーダーである。 find関数の実行時間は無視できるほど小さいと思うが、もし大きいようならば 自前でハッシュ関数を書いてみよう。
測定マシンの仕様は不明だが、ある測定では、100万回のfind実行時間が 680ms になっていた。 1回あたり 0.001ミリ秒にも満たないので、わがPCでも問題なく小さいであろう。
std::unordered_set<long>* faas[4] = { NULL };
void Render(int th, int minzoom, int maxzoom, int x, int y, int factor, int sock, Map* map) {
if (minzoom >= 17 && maxzoom != -1) {
std::unordered_set<long>* set = faas[minzoom-17];
long xy = (((long)x) << 32) + y;
auto it = set->find(xy);
if (it == set->end()) return; // FFAではない
}
// レンダリング処理(省略)
}
void LoadFAA(int zoom, std::unordered_set<long>* set) {
char path[256];
sprintf(path, "/media/sf_gis/sys/faa/faa%d.dat", zoom);
std::ifstream fin(path, std::ios::in | std::ios::binary);
if (!fin){
std::cout << "ファイル " << path << " が開けません\n";
return;
}
while(!fin.eof()){ //ファイルの最後まで続ける
long xy;
fin.read((char*)&xy, sizeof(long));
set->insert(xy);
}
fin.close(); //ファイルを閉じる
}
if (maxzoom >= 17 && faas[0] == NULL) {
// 最初のリクエストで全データを読み込んでおく
for (int zoom = 17; zoom <= 20; zoom++) {
faas[zoom-17] = new std::unordered_set<long>();
LoadFAA(zoom, faas[zoom-17]);
}
}
Render(n, minzoom, maxzoom, x, y, factor, client_sockfd, map);