質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

ハッシュ

ハッシュは、高速にデータ検索を行うアルゴリズムのことです。

Q&A

解決済

4回答

2802閲覧

C ハッシュテーブルの実装

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

ハッシュ

ハッシュは、高速にデータ検索を行うアルゴリズムのことです。

0グッド

1クリップ

投稿2016/06/13 03:34

###前提・実現したいこと
二次元平面上の点をデータとするハッシュ表をチェイニングで実装しようとしています。
乱数を用いてデータを生成し、最終的に生成した各バケットに登録されているデータの個数の統計量を導出したいです。

###発生している問題・エラーメッセージ
生成したハッシュ表を画面に出力しようとしたところ、Segmentation Fault: 11が表示されます。
一度print_hashでH[i]がNULLのときに出力したところ、H[B]すべてがNULLでした。
原因がわからないのでご教授よろしくお願いします。

###該当のソースコード

C

1 1 #include<stdio.h> 2 2 #include<stdlib.h> 3 3 #include<time.h> 4 4 #include<math.h> 5 5 #define B 10000 6 6 #define N 5 7 7 #define M 5000 //使用しません 8 8 #define X 10000 9 9 #define Y 10000 //使用しません 10 10 11 11 //二次元平面上の点 12 12 typedef struct POINT{ 13 13 int x; 14 14 int y; 15 15 }point_t; 16 16 17 17 //点の新規作成 18 18 point_t new_point(int x, int y) 19 19 { 20 20 point_t p; 21 21 p.x = x; 22 22 p.y = y; 23 23 return p; 24 24 } 25 25 26 26 //連結リストのノード 27 27 typedef struct NODE{ 28 28 point_t point; //登録する点 29 29 struct NODE *next; 30 30 }node_t; 31 31 32 32 //ノードの新規作成 33 33 node_t *new_node(point_t p) 34 34 { 35 35 node_t *ndPtr; 36 36 ndPtr = malloc(sizeof(node_t)); 37 37 38 38 if (ndPtr == NULL) { 39 39 return NULL; 40 40 } else { 41 41 ndPtr->point = p; 42 42 ndPtr->next = NULL; 43 43 } 44 44 45 45 return ndPtr; 46 46 } 47 47 48 48 //ハッシュ表 = ノードへのポインタを格納する配列 49 49 node_t *H[B]; 50 50 51 51 //ハッシュ表初期化関数 52 52 void init_hash() 53 53 { 54 54 int i; 55 55 for (i = 0; i < B; i++) H[i] = NULL; 56 56 } 57 57 58 58 //ハッシュ表出力関数 59 59 void print_hash(); 60 60 { 61 61 node_t *ndPtr; 62 62 int i; 63 63 64 64 for (i = 0; i < B; i++) { 65 65 ndPtr = H[i]; 66 66 if (ndPtr != NULL) { 67 67 printf("%6d %5d %5d\n", i, ndPtr->point.x, ndPtr->point.y); 68 68 ndPtr = ndPtr->next; 69 69 } 70 70 while (ndPtr != NULL) { 71 71 printf(" %5d %5d\n", ndPtr->point.x, ndPtr->point.y); 72 72 ndPtr = ndPtr->next; 73 73 } 74 74 } 75 75 } 76 76 77 77 //ハッシュ関数1 78 78 int hash1(point_t point) 79 79 { 80 80 int i; 81 81 for (i = 0; i <= X; i++) { 82 82 if (point.x == i) return i; 83 83 } 84 84 return -1; 85 85 } 86 86 87 87 //ノードの探索, *head:探索始点ノードへのポインタ, p:探す点 88 88 //見つかればそのアドレスを, 見つからなければNULLを返す 89 89 node_t *search_node(node_t *head, point_t p) 90 90 { 91 91 while (head != NULL) { 92 92 if (head->point.x == p.x && head->point.y == p.y) return head; 93 93 head = head->next; 94 94 } 95 95 return NULL; 96 96 } 97 97 98 98 //新しいノードをリストの先頭へ挿入, *head:先頭ノードへのポインタ, p:挿入する点 99 99 int insert_node_top(node_t **head, point_t p) 100100 { 101101 node_t *ndPtr; 102102 ndPtr = new_node(p); 103103 if (ndPtr == NULL) return -1; 104104 *head = ndPtr; 105105 return 1; 106106 } 107107 108108 //pointの探索, pがハッシュ表に含まれていれば1, 含まれていなければ0を返す 109109 int search_hash(point_t p) 110110 { 111111 int b; 112112 b = hash1(p); 113113 114114 if (search_node(H[b], p) != NULL) return 1; 115115 else return 0; 116116 } 117117 118118 //点をハッシュ表に重複なしで登録する関数 119119 int insert_hash(point_t p) 120120 { 121121 int b; 122122 b = hash1(p); 123123 124124 if (search_hash(p) == 0) { 125125 insert_node_top(&H[b], p); 126126 return 1; 127127 } 128128 else return 0; 129129 } 130130 131131 //各バケット(H[0], H[1],...)に登録されているデータの個数の最大値と最小値および分散 132132 void hash_status() 133133 { 134134 int max = 0, min = B; //登録データ数の最大値, 最小値 135135 double sum = 0; //登録データ数の和 136136 double ave, var, dif = 0; //平均, 分散, 二乗差 137137 int i; 138138 int count[B] = {}; //各バケットに登録されているデータの個数 139139 140140 for (i = 0; i < B; i++) { 141141 node_t *ndPtr; 142142 if (H[i] != NULL) { 143143 ndPtr = H[i]; 144144 while (ndPtr != NULL) { 145145 count[i]++; 146146 ndPtr = ndPtr->next; 147147 } 148148 if (count[i] > max) max = count[i]; 149149 if (count[i] < min) min = count[i]; 150150 sum += count[i]; 151151 } 152152 } 153153 154154 ave = sum / B; 155155 156156 for (i = 0; i < B; i++) { 157157 dif += pow(count[i] - ave, 2); 158158 } 159159 var = dif / B; 160160 161161 printf("MAX : %5d\n", max); 162162 printf("MIN : %5d\n", min); 163163 printf("VARIANCE : %5.5f\n", var); 164164 } 165165 166166 int main() 167167 { 168168 int i = 0; 169169 170170 init_hash(); 171171 172172 srand((unsigned)time(NULL)); //乱数生成 173173 174174 while (i < N) { 175175 int rx, ry; 176176 point_t p; 177177 178178 rx = rand() % B; //0-9999の整数 179179 ry = rand() % B; //0-9999の整数 180180 181181 if (rx >= ry) { 182182 p = new_point(rx, ry); 183183 if (insert_hash(p) == 1) i++; 184184 } 185185 } 186186 187187 print_hash(); 188188 189189 hash_status(); 190190 191191 return 0; 192192 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/13 04:11

main()のwhileループが終わったときの i の値はどうなっていますか?
guest

回答4

0

Ideoneで試したら動いてしまいました。
但し、60行目の文末にセミコロンがついていたので修正しましたが。

投稿2016/06/13 04:11

ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

軽く動かしてみました。
60行目の";"、hash_statusでint count[B]={0};、new_nodeで(node_t*)にキャストを変更してます。
とりあえず動きますが、new_nodeでmallocしたものが開放されてないと言われます。
多分そこが終了時にセグメントフォールトするのではないでしょうか?

投稿2016/06/13 08:13

pochi0701

総合スコア210

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

node_tのnextに代入しているのはnew_node関数の中でNULLを代入しているだけなので、nextを使おうとすると落ちるのでは?
nextには適切なポインタを設定する必要があると思います。
insert_node_topでheadがNULLの場合とそうでない場合に処理を分けて、NULLでない場合は新しく作成したnode_tのnextに元々のheadの値を代入するのが正しいのかな。

投稿2016/06/13 07:16

m-take

総合スコア249

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/14 01:43

insert_node_topでndPtr->next = *headを追加したら解決しました。 ありがとうございました。
guest

0

解答ではなく解決策の提案です。
ノードを作成・挿入している部分にバグがあるんでしょうから、それを順に追って正しいデータが得られているかどうかダンプしてみたらどうでしょう?

C

1int insert_hash(point_t p) 2{ 3 printf("insert_hash : p = (\d, \d)\n", p.x, p.y); 4 int b; 5 b = hash1(p); 6 printf("insert_hash : b=%d\n", b); 7 8 if (search_hash(p) == 0) { 9 printf("insert_hash : search_hash(p) == 0\n"); 10 insert_node_top(&H[b], p); 11 printf("insert_hash : H[b] = \x\n", H[b]); 12 return 1; 13 } 14 else return 0; 15}

投稿2016/06/13 04:04

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問