/****************************/ /* ハッシュ法( Hash ) */ /* coded by Y.Suganuma */ /****************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <string> #include <set> #include <unordered_set> #include <time.h> #include "MT.h" using namespace std; int hit = 0; /***********************************/ /* クラス Hash(ハッシュテーブル) */ /***********************************/ class Hash { int size; // ハッシュテーブルの大きさ set <string> *table; // 衝突リスト /*******************/ /* ハッシュ関数 */ /* s : 文字列 */ /*******************/ int hash(char *s) { unsigned int hash = 0; int len = strlen(s); for (int i1 = 0; i1 < len; i1++ ) { hash = (hash << 4) + s[i1]; // 左に4ビットシフトし文字を加える unsigned int g = hash & 0xf0000000; // ビット毎のAND if (g != 0) { hash ^= g >> 24; // 排他的論理和 hash ^= g; } } return hash % size; } public: /******************/ /* コンストラクタ */ /******************/ Hash(int sz) { size = sz; table = new set <string> [size]; } /***************************************/ /* データの追加 */ /* str : データ(文字列) */ /* return : =1 : 追加 */ /* =0 : 同じデータが存在 */ /***************************************/ int add(char *str) { int k = hash(str); if (!(table[k].empty())) hit++; pair<set<string>::iterator, bool> p = table[k].insert((string)str); return p.second; } /***********************************/ /* データの探索 */ /* str : データ(文字列) */ /* return : =1 : 見つかった */ /* =0 : 見つからない */ /***********************************/ int search(char *str) { int sw = 0; int k = hash(str); set<string>::iterator it = table[k].find((string)str); if (it != table[k].end()) sw = 1; return sw; } }; int main() { // 初期設定 int n = 0; char s[100000][11]; Hash H(10000000); init_genrand((unsigned)time(NULL)); // データの設定 printf("Hash\n"); clock_t tm1 = clock(); for (int i1 = 0; i1 < 5000000; i1++) { int k = genrand_int31(); char st[11]; gcvt((double)k, 11, st); st[strlen(st)-1] = '\0'; // 最後のピリオドが除かれる int sw = H.add(st); if (sw > 0) { if (i1%50 == 0 && n < 100000) { strcpy(s[n], st); n++; } } else i1--; } clock_t tm2 = clock(); printf(" 保存: %d ms, 衝突回数: %d\n", (int)(tm2-tm1), hit); // データの探索 for (int i1 = 0; i1 < n; i1++) { int sw = H.search(s[i1]); if (sw == 0) { printf("***error*** データが見つからない!\n"); exit(1); } } clock_t tm3 = clock(); printf(" 探索: %d ms\n", (int)(tm3-tm2)); // データの設定(string, unordered_set) n = 0; string* str = new string [100000]; printf("unordered_set(string)\n"); unordered_set<string> us; for (int i1 = 0; i1 < 5000000; i1++) { int k = genrand_int31(); char st[11]; gcvt((double)k, 11, st); st[strlen(st)-1] = '\0'; // 最後のピリオドが除かれる string sts(st); pair<unordered_set<string>::iterator, bool> sw = us.insert(sts); if (sw.second) { if (i1%50 == 0 && n < 100000) { str[n] = sts; n++; } } else i1--; } clock_t tm4 = clock(); printf(" 保存(string, unordered_set): %d ms\n", (int)(tm4-tm3)); // データの探索(string, unordered_set) for (int i1 = 0; i1 < n; i1++) { unordered_set<string>::iterator it = us.find(str[i1]); if (it == us.end()) { printf("***error*** データが見つからない!\n"); exit(1); } } clock_t tm5 = clock(); printf(" 探索(string, unordered_set): %d ms\n", (int)(tm5-tm4)); // データの設定(int, unordered_set) n = 0; int kk[100000]; printf("unordered_set(int)\n"); unordered_set<int> usi; for (int i1 = 0; i1 < 5000000; i1++) { int k = genrand_int31(); pair<unordered_set<int>::iterator, bool> sw = usi.insert(k); if (sw.second) { if (i1%50 == 0 && n < 100000) { kk[n] = k; n++; } } else i1--; } clock_t tm6 = clock(); printf(" 保存(int, unordered_set): %d ms\n", (int)(tm6-tm5)); // データの探索(int, unordered_set) for (int i1 = 0; i1 < n; i1++) { unordered_set<int>::iterator it = usi.find(kk[i1]); if (it == usi.end()) { printf("***error*** データが見つからない!\n"); exit(1); } } clock_t tm7 = clock(); printf(" 探索(int, unordered_set): %d ms\n", (int)(tm7-tm6)); return 0; }