/****************************/
/* ハッシュ法( 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;
}