質問編集履歴
7
もう少し情報を追加しました
title
CHANGED
File without changes
|
body
CHANGED
@@ -514,4 +514,9 @@
|
|
514
514
|
・
|
515
515
|
・
|
516
516
|
```
|
517
|
-
が延々と続いてしまうのです!!!!!
|
517
|
+
が延々と続いてしまうのです!!!!!
|
518
|
+
|
519
|
+
編集2:
|
520
|
+
ごめんなさい、よく考えたらr=hash_search(H, s);→slist_insert_tail(L, r);のときは次のリストの要素を指すポインタもそのままコピーされるのですから、そりゃ無限ループになりますよね、、、
|
521
|
+
|
522
|
+
もう少し考えます
|
6
質問文に説明を追加
title
CHANGED
File without changes
|
body
CHANGED
@@ -492,7 +492,7 @@
|
|
492
492
|
return 0;
|
493
493
|
}
|
494
494
|
```
|
495
|
-
例えば、
|
495
|
+
例えば、ハッシュ関数が常に1を出力するよう変更し、
|
496
496
|
```
|
497
497
|
3
|
498
498
|
coffee コーヒー
|
5
コードにコメントした
title
CHANGED
File without changes
|
body
CHANGED
@@ -419,7 +419,7 @@
|
|
419
419
|
int h=hfunc(H, key);
|
420
420
|
p = H.T[h]->head;
|
421
421
|
while(p!=NULL){
|
422
|
-
if(string_compare(p->key, key)==0){
|
422
|
+
if(string_compare(p->key, key)==0){ //keyと一致するような要素を同じスロットにあるリストから探索していきます
|
423
423
|
return p;
|
424
424
|
}
|
425
425
|
p = p->next;
|
4
コードを書き直しましたが、やはりうまくいきません
title
CHANGED
File without changes
|
body
CHANGED
@@ -259,4 +259,259 @@
|
|
259
259
|
|
260
260
|
自分で調べててみたところ、どうもハッシュ関数を改良したほうがよさそうなので、mの値を数万程度ではなく数百万程度の素数に変えるなどをしてみました。しかし、mにどのような値を入れてもうまくいきません。
|
261
261
|
|
262
|
-
どこを改良するべきか、アドバイスいただけるでしょうか。宜しくお願いします。
|
262
|
+
どこを改良するべきか、アドバイスいただけるでしょうか。宜しくお願いします。
|
263
|
+
|
264
|
+
編集:
|
265
|
+
衝突が起きる場合を想定して書き直しましたが、今度は同じスロットの要素を出力するときにおかしくなります。
|
266
|
+
```C
|
267
|
+
#include <stdio.h>
|
268
|
+
#include <string.h>
|
269
|
+
#include <stdlib.h>
|
270
|
+
#include <math.h>
|
271
|
+
|
272
|
+
#define NEW(p, n){p = malloc((n)*sizeof(p[0]));}
|
273
|
+
|
274
|
+
typedef char* String;
|
275
|
+
//後々使いやすくするため、ここでStringタイプを定義しちゃいます
|
276
|
+
|
277
|
+
//英和辞書用のオブジェクトです(英語の見出しと日本語の意味のペア)
|
278
|
+
typedef struct slobj_{
|
279
|
+
struct slobj_* next;
|
280
|
+
String key;
|
281
|
+
String jpn;
|
282
|
+
}* slobj;
|
283
|
+
|
284
|
+
//連結リスト
|
285
|
+
typedef struct{
|
286
|
+
slobj head;
|
287
|
+
slobj tail;
|
288
|
+
}* slist;
|
289
|
+
|
290
|
+
typedef struct{
|
291
|
+
int n; //ハッシュに格納されている要素数
|
292
|
+
int m; //ハッシュ表のサイズ
|
293
|
+
slist* T; //リストの配列
|
294
|
+
} hash;
|
295
|
+
|
296
|
+
ハッシュ関数
|
297
|
+
int hfunc(hash H, String key){
|
298
|
+
int h=0, i=0;
|
299
|
+
while (key[i] != 0){
|
300
|
+
h = h*3659+key[i]; //ハッシュ値を計算
|
301
|
+
i++;
|
302
|
+
}
|
303
|
+
return abs(h) % H.m; //非負の値にして、表のサイズで割った余り
|
304
|
+
//return 1; //ハッシュ関数が全て同じ値を出す場合で実験してみました。
|
305
|
+
}
|
306
|
+
|
307
|
+
//文字列の長さを求める
|
308
|
+
int string_len(String str){
|
309
|
+
int len=0;
|
310
|
+
while(str[len]!=0){
|
311
|
+
len++;
|
312
|
+
}
|
313
|
+
return len;
|
314
|
+
}
|
315
|
+
|
316
|
+
//文字列を標準入力から読む
|
317
|
+
String string_input(void){
|
318
|
+
int i, len;
|
319
|
+
char buf[1000];
|
320
|
+
String str;
|
321
|
+
scanf("%999s", buf);
|
322
|
+
|
323
|
+
len = string_len(buf);
|
324
|
+
|
325
|
+
NEW(str, len+1);
|
326
|
+
for(i=0; i<len; i++){
|
327
|
+
str[i]=buf[i];
|
328
|
+
}
|
329
|
+
str[len] = 0;
|
330
|
+
return str;
|
331
|
+
}
|
332
|
+
|
333
|
+
//文字列が同じかどうかを判定する関数
|
334
|
+
int string_compare(String p, String q){
|
335
|
+
int c1, c2;
|
336
|
+
int i=0;
|
337
|
+
while(1){
|
338
|
+
c1=p[i]; c2=q[i];
|
339
|
+
if(c1<c2) return -1;
|
340
|
+
if(c1>c2) return 1;
|
341
|
+
if(c1==0) break;
|
342
|
+
i++;
|
343
|
+
}
|
344
|
+
return 0;
|
345
|
+
}
|
346
|
+
|
347
|
+
//新しい連結リストを作成
|
348
|
+
slist slist_new(void){
|
349
|
+
slist L;
|
350
|
+
NEW(L, 1);
|
351
|
+
L -> head = NULL;
|
352
|
+
L -> tail = NULL;
|
353
|
+
return L;
|
354
|
+
}
|
355
|
+
|
356
|
+
//新しいリスト要素(つまり英和辞典における英語の見出しと対応する日本語のペア)
|
357
|
+
slobj slobj_new(String x, String y){
|
358
|
+
slobj p;
|
359
|
+
NEW(p, 1);
|
360
|
+
p -> key = x;
|
361
|
+
p -> jpn = y;
|
362
|
+
p -> next = NULL;
|
363
|
+
return p;
|
364
|
+
}
|
365
|
+
|
366
|
+
//連結リストの先頭に挿入
|
367
|
+
void slist_insert_head(slist L, slobj p){
|
368
|
+
p -> next = L -> head;
|
369
|
+
L -> head = p;
|
370
|
+
}
|
371
|
+
|
372
|
+
//連結リストの末尾に挿入
|
373
|
+
void slist_insert_tail(slist L, slobj p){
|
374
|
+
if(L -> head == NULL){
|
375
|
+
L -> tail = p;
|
376
|
+
L -> head = p;
|
377
|
+
}
|
378
|
+
else if(L -> head == L -> tail){
|
379
|
+
L -> tail = p;
|
380
|
+
L -> head -> next = p;
|
381
|
+
}
|
382
|
+
else{
|
383
|
+
L -> tail -> next = p;
|
384
|
+
L -> tail = p;
|
385
|
+
}
|
386
|
+
}
|
387
|
+
|
388
|
+
//連結リストをプリント
|
389
|
+
void slist_print(slist L)
|
390
|
+
{
|
391
|
+
slobj p;
|
392
|
+
p = L->head;
|
393
|
+
while (p != NULL){
|
394
|
+
if(string_compare(p->jpn, "NO")==0){
|
395
|
+
printf("%s\n", p->jpn);
|
396
|
+
}
|
397
|
+
else{
|
398
|
+
printf("%s %s\n", p -> key, p -> jpn);
|
399
|
+
}
|
400
|
+
p = p-> next;
|
401
|
+
}
|
402
|
+
}
|
403
|
+
|
404
|
+
//表のサイズがmのハッシュ表を作る
|
405
|
+
hash hash_new(int m){
|
406
|
+
hash H;
|
407
|
+
int i;
|
408
|
+
NEW(H.T, m);
|
409
|
+
H.m = m;
|
410
|
+
for(i=0; i<= m-1; i++){
|
411
|
+
H.T[i]=slist_new();
|
412
|
+
}
|
413
|
+
return H;
|
414
|
+
}
|
415
|
+
|
416
|
+
//キーがkeyである要素を返す
|
417
|
+
slobj hash_search(hash H, String key){
|
418
|
+
slobj p;
|
419
|
+
int h=hfunc(H, key);
|
420
|
+
p = H.T[h]->head;
|
421
|
+
while(p!=NULL){
|
422
|
+
if(string_compare(p->key, key)==0){
|
423
|
+
return p;
|
424
|
+
}
|
425
|
+
p = p->next;
|
426
|
+
}
|
427
|
+
return p;
|
428
|
+
}
|
429
|
+
|
430
|
+
//ハッシュに入力する関数。同じスロットにハッシュされたすべての要素が連結リストに格納されるようにします。
|
431
|
+
void hash_insert(hash H, slobj obj){
|
432
|
+
int h=hfunc(H, obj->key);
|
433
|
+
slist_insert_head(H.T[h], obj);
|
434
|
+
}
|
435
|
+
|
436
|
+
void slist_free(slist L){
|
437
|
+
slobj p, q, r;
|
438
|
+
p = L->head;
|
439
|
+
q = p->next;
|
440
|
+
while (q != NULL){
|
441
|
+
r = q;
|
442
|
+
q = q-> next;
|
443
|
+
free(p);
|
444
|
+
p = r;
|
445
|
+
}
|
446
|
+
free(p);
|
447
|
+
free(L);
|
448
|
+
}
|
449
|
+
|
450
|
+
void hash_free(hash H){
|
451
|
+
int i;
|
452
|
+
for(i = 0; i <= H.m-1; i++){
|
453
|
+
if(H.T[i] -> head != NULL){
|
454
|
+
slist_free(H.T[i]);
|
455
|
+
}
|
456
|
+
}
|
457
|
+
free(H.T);
|
458
|
+
}
|
459
|
+
|
460
|
+
int main(){
|
461
|
+
int i, j, k, n;
|
462
|
+
String eng, jpn, s;
|
463
|
+
double v;
|
464
|
+
slobj p, r;
|
465
|
+
hash H;
|
466
|
+
slist L=slist_new(); //ここに出力する実数を格納していく
|
467
|
+
int m=81239; //数千から数万程度の素数がいいらしい
|
468
|
+
//ここから英和辞典を作成します。
|
469
|
+
scanf("%d", &n); //英和辞典に記録していく英語日本語ペアの数
|
470
|
+
H=hash_new(m);
|
471
|
+
H.n = n;
|
472
|
+
//英語日本語ペアを順次入れていく
|
473
|
+
for(i=1; i<=n; i++){
|
474
|
+
eng=string_input();
|
475
|
+
jpn=string_input();
|
476
|
+
p=slobj_new(eng, jpn);
|
477
|
+
hash_insert(H, p);
|
478
|
+
}
|
479
|
+
//ここからはkeyを入力していきます。各keyに対応する英和辞典の見出しがある場合はそのkeyおよびそれに対応する日本語を、ない場合は-1と出力します
|
480
|
+
scanf("%d", &k);//以後の問い合わせの数
|
481
|
+
for(j=1; j<=k; j++){
|
482
|
+
s=string_input();
|
483
|
+
r=hash_search(H, s);
|
484
|
+
if(r==NULL){
|
485
|
+
r=slobj_new(NULL, "NO");
|
486
|
+
}
|
487
|
+
slist_insert_tail(L, r);
|
488
|
+
}
|
489
|
+
slist_print(L);
|
490
|
+
//slist_free(L);
|
491
|
+
//hash_free(H);
|
492
|
+
return 0;
|
493
|
+
}
|
494
|
+
```
|
495
|
+
例えば、
|
496
|
+
```
|
497
|
+
3
|
498
|
+
coffee コーヒー
|
499
|
+
milk 牛乳
|
500
|
+
water 水
|
501
|
+
2
|
502
|
+
milk
|
503
|
+
coffee
|
504
|
+
```
|
505
|
+
という入力にした場合、
|
506
|
+
```
|
507
|
+
milk 牛乳
|
508
|
+
coffee コーヒー
|
509
|
+
milk 牛乳
|
510
|
+
coffee コーヒー
|
511
|
+
milk 牛乳
|
512
|
+
coffee コーヒー
|
513
|
+
・
|
514
|
+
・
|
515
|
+
・
|
516
|
+
```
|
517
|
+
が延々と続いてしまうのです!!!!!
|
3
文章を追加
title
CHANGED
File without changes
|
body
CHANGED
@@ -255,7 +255,7 @@
|
|
255
255
|
aucltz
|
256
256
|
(中略)
|
257
257
|
```
|
258
|
-
のような長いインプット
|
258
|
+
のような長いインプットだと、間違ったkeyに対応する見出しが何個か出力されてしまい、正しく動作しないようです。
|
259
259
|
|
260
260
|
自分で調べててみたところ、どうもハッシュ関数を改良したほうがよさそうなので、mの値を数万程度ではなく数百万程度の素数に変えるなどをしてみました。しかし、mにどのような値を入れてもうまくいきません。
|
261
261
|
|
2
コードの修正
title
CHANGED
File without changes
|
body
CHANGED
@@ -34,10 +34,9 @@
|
|
34
34
|
int hfunc(hash H, String key){
|
35
35
|
int h=0, i=0;
|
36
36
|
while (key[i] != 0){
|
37
|
-
h = h*
|
37
|
+
h = h*101+key[i]; //ハッシュ値を計算
|
38
38
|
i++;
|
39
39
|
}
|
40
|
-
h = h*1000;
|
41
40
|
return abs(h) % H.m; //非負の値にして、表のサイズで割った余り
|
42
41
|
}
|
43
42
|
|
1
タイトルの変更
title
CHANGED
@@ -1,1 +1,1 @@
|
|
1
|
-
ハッシュ関数の選び方についてアドバイスを頂きたいです。
|
1
|
+
英和辞書を作成しているのですが、ハッシュ関数の選び方についてアドバイスを頂きたいです。
|
body
CHANGED
File without changes
|