teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

14

修正しました

2020/12/02 08:18

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -180,12 +180,30 @@
180
180
  }
181
181
 
182
182
  /* 二分木を通りがけ順でなぞる */
183
+ /* 全要素を昇順に表示する関数
184
+ 二分探索木の全要素を小→大の順で表示する */
185
+ /* 全体の流れ
186
+ ある要素の左枝先を全部調べ終えたら、自身の値を出力し、
187
+ 次にその要素の右枝先の要素を全部調べる
188
+ 左枝を調べる
189
+ 調べ終えたら戻ってくる
190
+ 値を出力する
191
+ 右枝を調べる
192
+ 調べ終えたら戻ってくる
193
+ 関数を終了して、自身を呼び出した関数の元へと戻る */
183
194
  void inorder(NODE *p)
184
195
  {
185
196
  /* 木が空なら何もしない */
186
197
  if(p==NULL)
187
198
  return;
188
- els
199
+ else{
200
+ /* 引数に左へのポインタを渡すことで、再帰を繰り返して延々と左枝へ移動し
201
+ 一番左、一番小さい値にたどり着く
202
+ 子ノードはないため、引数の値はNULLに当たって戻ってくる
203
+ 一番下位の要素なので、左枝と同様に右枝もない。
204
+ なので終点である NULL に行き当たり、また return で戻ってくる。
205
+ そして「一番左を操作する関数」は処理を終える。
206
+ この関数に戻り値はない。「画面に出力」して、それで終了*/
189
207
  inorder(p->left); /* 左ノードへ移動 */
190
208
  printf("%d ",p->data); /* 自身の値を出力 */
191
209
  inorder(p->right); /* 右ノードへ移動 */
@@ -211,7 +229,7 @@
211
229
  int main(void)
212
230
  {
213
231
  int a,key;
214
- int mn=0;
232
+ int mn=0;
215
233
 
216
234
  printf("二分探索木をします\n");
217
235
  do{
@@ -262,7 +280,7 @@
262
280
  }while (mn !=9);
263
281
  return 0;
264
282
  }
265
- ````
283
+ ``
266
284
  ```### 前提・実現したいこと``````
267
285
  二分探索木のプログラムを実装したいです
268
286
  仕様は

13

誤字の修正です

2020/12/02 08:18

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -180,32 +180,14 @@
180
180
  }
181
181
 
182
182
  /* 二分木を通りがけ順でなぞる */
183
- /* 全要素を昇順に表示する関数
184
- 二分探索木の全要素を小→大の順で表示する */
185
- /* 全体の流れ
186
- ある要素の左枝先を全部調べ終えたら、自身の値を出力し、
187
- 次にその要素の右枝先の要素を全部調べる
188
- 左枝を調べる
189
- 調べ終えたら戻ってくる
190
- 値を出力する
191
- 右枝を調べる
192
- 調べ終えたら戻ってくる
193
- 関数を終了して、自身を呼び出した関数の元へと戻る */
194
183
  void inorder(NODE *p)
195
184
  {
196
185
  /* 木が空なら何もしない */
197
186
  if(p==NULL)
198
187
  return;
199
- else{
188
+ els
200
- /* 引数に左へのポインタを渡すことで、再帰を繰り返して延々と左枝へ移動し
201
- 一番左、一番小さい値にたどり着く
202
- 子ノードはないため、引数の値はNULLに当たって戻ってくる
203
- 一番下位の要素なので、左枝と同様に右枝もない。
204
- なので終点である NULL に行き当たり、また return で戻ってくる。
205
- そして「一番左を操作する関数」は処理を終える。
206
- この関数に戻り値はない。「画面に出力」して、それで終了*/
207
189
  inorder(p->left); /* 左ノードへ移動 */
208
- printf("%d",p->data); /* 自身の値を出力 */
190
+ printf("%d ",p->data); /* 自身の値を出力 */
209
191
  inorder(p->right); /* 右ノードへ移動 */
210
192
  }
211
193
  /* 関数を終了して、自身を呼び出した関数のもとへ戻る */
@@ -221,7 +203,7 @@
221
203
  else{
222
204
  postorder(p->left); /* 左ノードへ移動 */
223
205
  postorder(p->right); /* 右ノードへ移動 */
224
- printf("%d",p->data); /* 自身の値を出力 */
206
+ printf("%d ",p->data); /* 自身の値を出力 */
225
207
  }
226
208
 
227
209
  }

12

見やすくしました

2020/12/02 07:50

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -55,25 +55,29 @@
55
55
  while (p != NULL) {
56
56
  /* キーと注目している節のデータが等しいか比較 */
57
57
  if (key == p->data){
58
- /* もしキーと注目している節のデータとが等しければポインタを関数として返す */
58
+ /* もしキーと注目している節のデータとが等しければポインタを関数として返す */
59
- printf("探索した値の番地です>>%d\n",p);
59
+ printf("探索した値の番地です>>%p\n",p);
60
- return p;
60
+ return p;
61
- }else{
62
- if (key < p->data)
61
+ }else if (key < p->data){
63
62
  /* キーの方が小さければ左部分木に進む */
64
63
  p = p->left;
65
- else
64
+ }else{
66
65
  /* キーの方が大きければ右部分木に進む*/
67
66
  p = p->right;
68
- }
69
67
  }
70
68
  /* ループを抜け出たということは見付からなかったというと
71
69
  NULL返して失敗したことを知らせる */
72
70
  printf("NotExist\n");
73
71
  return NULL;
72
+ }
74
73
  }
75
74
 
76
75
  /* 二分探索木から要素を追加する関数*/
76
+ /* 探索と同じ要領で木を辿り、辿るべき部分木がなければそこに挿入する */
77
+ /* 挿入した要素が置かれる節へのポインタを返す
78
+ すでに要素が登録されているのなら、何もしないでNULLを返す
79
+ key:挿入するデータ
80
+ NODE型へのポインターが戻り値 */
77
81
  NODE *insert(int key)
78
82
  {
79
83
  NODE **p,*new;
@@ -84,13 +88,12 @@
84
88
  /* キーと注目している節のデータが等しいか比較 */
85
89
  if (key == (*p)->data){
86
90
  /* すでに登録されている */
87
- printf("AlreadyExsits\n");
91
+ printf("AlreadyExsits\n");
88
- return NULL;
92
+ return NULL;
89
- }else{
90
- if (key < (*p)->data)
93
+ }else if (key < (*p)->data){
91
94
  /* キーの方が小さければ左部分木に進む */
92
95
  p =&(*p)->left;
93
- else
96
+ }else{
94
97
  /* キーの方が大きければ右部分木に進む */
95
98
  p =&(*p)->right;
96
99
  }
@@ -117,7 +120,7 @@
117
120
  key:削除するデータ */
118
121
  int delete(int key)
119
122
  {
120
- /* 親へのポインタを使う */
123
+ /* 親へのポインタを使う */
121
124
  NODE **p, *x;
122
125
  /* 変数pが変数rootを指すように初期化する */
123
126
  p = &root;
@@ -129,32 +132,32 @@
129
132
  if (key == (*p)->data) {
130
133
  x = *p;
131
134
  /* 1つも子を持っていない、葉である場合 */
132
- if (x->left == NULL && x->right == NULL) {
135
+ if (x->left == NULL && x->right == NULL){
133
- *p = NULL;
136
+ *p = NULL;
134
- /* 右の子のみをもつ */
137
+ /* 右の子のみをもつ */
135
- if (x->left == NULL) {
138
+ }else if (x->left == NULL){
136
- *p = x->right;
139
+ *p = x->right;
137
140
  /* 左の子のみをもつ */
138
- } else if (x->right == NULL) {
141
+ }else if (x->right == NULL){
139
142
  *p = x->left;
140
143
  /* 左右2つの子を持つ */
141
- } else {
144
+ }else{
142
- /* 部分木から最小の要素を取り去る */
145
+ /* 部分木から最小の要素を取り去る */
143
- *p = deletemin(&x->right);
146
+ *p = deletemin(&x->right);
144
- (*p)->right = x->right;
147
+ (*p)->right = x->right;
145
- (*p)->left = x->left;
148
+ (*p)->left = x->left;
146
- }
149
+ }
147
- /* 取り除いた節を解放させる */
150
+ /* 取り除いた節を解放させる */
148
- free(x);
151
+ free(x);
149
- printf("Done\n");
152
+ printf("Done\n");
150
- return 1;
153
+ return 1;
151
154
 
152
- } else if (key < (*p)->data)
155
+ }else if (key < (*p)->data){
153
- /* 左部分木に進む */
156
+ /* 左部分木に進む */
154
- p = &(*p)->left;
157
+ p = &(*p)->left;
155
- else
158
+ }else{
156
- /* 右部分木に進む */
159
+ /* 右部分木に進む */
157
- p = &(*p)->right;
160
+ p = &(*p)->right;
158
161
  }
159
162
  }
160
163
  /* 削除対象が見つからなかった */
@@ -162,8 +165,6 @@
162
165
  return 0;
163
166
  }
164
167
 
165
-
166
-
167
168
  /* 二分木を行きがけ順でなぞる */
168
169
  void preorder(NODE *p)
169
170
  {
@@ -171,20 +172,44 @@
171
172
  if(p==NULL)
172
173
  return;
173
174
  else{
174
- printf("%d",p->data); /* 自身の値を出力 */
175
+ printf("%d ",p->data); /* 自身の値を出力 */
175
176
  preorder(p->left); /* 左ノードへ移動 */
176
177
  preorder(p->right); /* 右ノードへ移動 */
177
178
  }
179
+
178
180
  }
179
181
 
180
182
  /* 二分木を通りがけ順でなぞる */
183
+ /* 全要素を昇順に表示する関数
184
+ 二分探索木の全要素を小→大の順で表示する */
185
+ /* 全体の流れ
186
+ ある要素の左枝先を全部調べ終えたら、自身の値を出力し、
187
+ 次にその要素の右枝先の要素を全部調べる
188
+ 左枝を調べる
189
+ 調べ終えたら戻ってくる
190
+ 値を出力する
191
+ 右枝を調べる
192
+ 調べ終えたら戻ってくる
193
+ 関数を終了して、自身を呼び出した関数の元へと戻る */
181
194
  void inorder(NODE *p)
182
195
  {
183
196
  /* 木が空なら何もしない */
184
197
  if(p==NULL)
185
198
  return;
186
199
  else{
200
+ /* 引数に左へのポインタを渡すことで、再帰を繰り返して延々と左枝へ移動し
201
+ 一番左、一番小さい値にたどり着く
202
+ 子ノードはないため、引数の値はNULLに当たって戻ってくる
203
+ 一番下位の要素なので、左枝と同様に右枝もない。
204
+ なので終点である NULL に行き当たり、また return で戻ってくる。
205
+ そして「一番左を操作する関数」は処理を終える。
206
+ この関数に戻り値はない。「画面に出力」して、それで終了*/
207
+ inorder(p->left); /* 左ノードへ移動 */
208
+ printf("%d",p->data); /* 自身の値を出力 */
209
+ inorder(p->right); /* 右ノードへ移動 */
187
- }
210
+ }
211
+ /* 関数を終了して、自身を呼び出した関数のもとへ戻る */
212
+
188
213
  }
189
214
 
190
215
  /* 二分木を帰りがけ順でなぞる */
@@ -194,20 +219,21 @@
194
219
  if(p==NULL)
195
220
  return;
196
221
  else{
197
- postorder(p->left); /* 左ノードへ移動 */
222
+ postorder(p->left); /* 左ノードへ移動 */
198
223
  postorder(p->right); /* 右ノードへ移動 */
199
224
  printf("%d",p->data); /* 自身の値を出力 */
200
225
  }
226
+
201
227
  }
202
228
 
203
229
  int main(void)
204
230
  {
205
- int a,key1,key2;
231
+ int a,key;
206
232
  int mn=0;
207
233
 
208
234
  printf("二分探索木をします\n");
209
235
  do{
210
- printf("メニューを選んでください\n\n1=追加\n2=行きがけ順\n3=通りがけ順\n4=帰りがけ順\n5=指定した値の番地\n6=削除\n9=終了\n");
236
+ printf("\nメニューを選んでください\n1=追加 2=行きがけ順 3=通りがけ順 4=帰りがけ順 5=指定した値の番地 6=削除 9=終了\n");
211
237
  scanf("%d",&mn);
212
238
  switch(mn){
213
239
 
@@ -234,14 +260,14 @@
234
260
 
235
261
  case 5:
236
262
  printf("指定した値の番地を出力します\n");
237
- scanf("%d",&key1);
263
+ scanf("%d",&key);
238
- search(key1);
264
+ search(key);
239
265
  break;
240
266
 
241
267
  case 6:
242
268
  printf("指定した値を削除します\n");
243
- scanf("%d",&key2);
269
+ scanf("%d",&key);
244
- delete(key2);
270
+ delete(key);
245
271
  break;
246
272
 
247
273
  case 9:
@@ -252,11 +278,9 @@
252
278
  printf("エラー:メニューの中の数字を入力してください\n");
253
279
  }
254
280
  }while (mn !=9);
255
-
256
- kaihou();
257
281
  return 0;
258
282
  }
259
- ``
283
+ ````
260
284
  ```### 前提・実現したいこと``````
261
285
  二分探索木のプログラムを実装したいです
262
286
  仕様は

11

インデントをきちんとしました

2020/12/02 07:48

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -74,11 +74,6 @@
74
74
  }
75
75
 
76
76
  /* 二分探索木から要素を追加する関数*/
77
- /* 探索と同じ要領で木を辿り、辿るべき部分木がなければそこに挿入する */
78
- /* 挿入した要素が置かれる節へのポインタを返す
79
- すでに要素が登録されているのなら、何もしないでNULLを返す
80
- key:挿入するデータ
81
- NODE型へのポインターが戻り値 */
82
77
  NODE *insert(int key)
83
78
  {
84
79
  NODE **p,*new;
@@ -122,49 +117,49 @@
122
117
  key:削除するデータ */
123
118
  int delete(int key)
124
119
  {
125
- /* 親へのポインタを使う */
120
+ /* 親へのポインタを使う */
126
- NODE **p,*x;
121
+ NODE **p, *x;
127
- /* 変数pが変数rootを指すように初期化する */
122
+ /* 変数pが変数rootを指すように初期化する */
128
- p=&root;
123
+ p = &root;
129
- /* 削除対象となる要素を探す */
124
+ /* 削除対象となる要素を探す */
130
- while (*p != NULL) {
125
+ while (*p != NULL) {
131
- /* 見つかった
126
+ /* 見つかった
132
- 変数pは削除される節の親のメンバleft,right
127
+ 変数pは削除される節の親のメンバleft,right
133
- 変数xは削除される節そのものを指している */
128
+ 変数xは削除される節そのものを指している */
134
- if (key == (*p)->data){
129
+ if (key == (*p)->data) {
135
- x=*p;
130
+ x = *p;
136
- /* 1つも子を持っていない、葉である場合 */
131
+ /* 1つも子を持っていない、葉である場合 */
137
- if(x->left==NULL && x->right==NULL){
132
+ if (x->left == NULL && x->right == NULL) {
138
- *p=NULL;
133
+ *p = NULL;
139
- /* 右の子のみをもつ */
134
+ /* 右の子のみをもつ */
140
- if(x->left==NULL){
135
+ if (x->left == NULL) {
141
- *p=x->right;
136
+ *p = x->right;
142
- /* 左の子のみをもつ */
137
+ /* 左の子のみをもつ */
143
- }else if(x->right==NULL){
138
+ } else if (x->right == NULL) {
144
- *p=x->left;
139
+ *p = x->left;
145
- /* 左右2つの子を持つ */
140
+ /* 左右2つの子を持つ */
146
- }else{
141
+ } else {
147
- /* 部分木から最小の要素を取り去る */
142
+ /* 部分木から最小の要素を取り去る */
148
- *p=deletemin(&x->right);
143
+ *p = deletemin(&x->right);
149
- (*p)->right=x->right;
144
+ (*p)->right = x->right;
150
- (*p)->left=x->left;
145
+ (*p)->left = x->left;
151
- }
146
+ }
152
- /* 取り除いた節を解放させる */
147
+ /* 取り除いた節を解放させる */
153
- free(x);
148
+ free(x);
154
- printf("Done\n");
149
+ printf("Done\n");
155
- return 1;
150
+ return 1;
156
-
151
+
157
- }else if(key < (*p)->data)
152
+ } else if (key < (*p)->data)
158
- /* 左部分木に進む */
153
+ /* 左部分木に進む */
159
- p=&(*p)->left;
154
+ p = &(*p)->left;
160
- else
155
+ else
161
- /* 右部分木に進む */
156
+ /* 右部分木に進む */
162
- p=&(*p)->right;
157
+ p = &(*p)->right;
163
- }
158
+ }
164
- }
159
+ }
165
- /* 削除対象が見つからなかった */
160
+ /* 削除対象が見つからなかった */
166
- printf("NotExist\n");
161
+ printf("NotExist\n");
167
- return 0;
162
+ return 0;
168
163
  }
169
164
 
170
165
 

10

コードをコピペし直しました ながいコメントを削除しました

2020/12/02 03:16

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -1,4 +1,4 @@
1
- ``````ここに言語を入力
1
+ ```ここに言語を入力
2
2
  コード
3
3
  `#include <stdio.h>
4
4
  #include <stdlib.h>
@@ -131,13 +131,13 @@
131
131
  /* 見つかった
132
132
  変数pは削除される節の親のメンバleft,right
133
133
  変数xは削除される節そのものを指している */
134
- if (key == (*p)->data){  
134
+ if (key == (*p)->data){
135
135
  x=*p;
136
136
  /* 1つも子を持っていない、葉である場合 */
137
- if(x->left==NULL && x->right==NULL){    
137
+ if(x->left==NULL && x->right==NULL){
138
138
  *p=NULL;
139
139
  /* 右の子のみをもつ */
140
- if(x->left==NULL){  //ここからif文の書き方変えました
140
+ if(x->left==NULL){
141
141
  *p=x->right;
142
142
  /* 左の子のみをもつ */
143
143
  }else if(x->right==NULL){
@@ -183,35 +183,13 @@
183
183
  }
184
184
 
185
185
  /* 二分木を通りがけ順でなぞる */
186
- /* 全要素を昇順に表示する関数
187
- 二分探索木の全要素を小→大の順で表示する */
188
- /* 全体の流れ
189
- ある要素の左枝先を全部調べ終えたら、自身の値を出力し、
190
- 次にその要素の右枝先の要素を全部調べる
191
- 左枝を調べる
192
- 調べ終えたら戻ってくる
193
- 値を出力する
194
- 右枝を調べる
195
- 調べ終えたら戻ってくる
196
- 関数を終了して、自身を呼び出した関数の元へと戻る */
197
186
  void inorder(NODE *p)
198
187
  {
199
188
  /* 木が空なら何もしない */
200
189
  if(p==NULL)
201
190
  return;
202
191
  else{
203
- /* 引数に左へのポインタを渡すことで、再帰を繰り返して延々と左枝へ移動し
204
- 一番左、一番小さい値にたどり着く
205
- 子ノードはないため、引数の値はNULLに当たって戻ってくる
206
- 一番下位の要素なので、左枝と同様に右枝もない。
207
- なので終点である NULL に行き当たり、また return で戻ってくる。
208
- そして「一番左を操作する関数」は処理を終える。
209
- この関数に戻り値はない。「画面に出力」して、それで終了*/
210
- inorder(p->left); /* 左ノードへ移動 */
211
- printf("%d",p->data); /* 自身の値を出力 */
212
- inorder(p->right); /* 右ノードへ移動 */
213
- }
192
+ }
214
- /* 関数を終了して、自身を呼び出した関数のもとへ戻る */
215
193
  }
216
194
 
217
195
  /* 二分木を帰りがけ順でなぞる */
@@ -227,7 +205,6 @@
227
205
  }
228
206
  }
229
207
 
230
-
231
208
  int main(void)
232
209
  {
233
210
  int a,key1,key2;
@@ -239,7 +216,6 @@
239
216
  scanf("%d",&mn);
240
217
  switch(mn){
241
218
 
242
-
243
219
  case 1:
244
220
  printf("追加する数字を入力してください\n");
245
221
  scanf("%d",&a);
@@ -282,6 +258,7 @@
282
258
  }
283
259
  }while (mn !=9);
284
260
 
261
+ kaihou();
285
262
  return 0;
286
263
  }
287
264
  ``

9

エラーをほとんど消しました

2020/12/02 03:05

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -1,12 +1,15 @@
1
+ ``````ここに言語を入力
1
- ```
2
+ コード
2
3
  `#include <stdio.h>
3
- #include <stdlib.h>
4
+ #include <stdlib.h>
5
+
4
6
  /* 木の節の定義 */
5
7
  typedef struct node{
6
8
  int data; /* 探索のキーになるデータ型 */
7
9
  struct node *left; /* 左の子 */
8
10
  struct node *right; /* 右の子 */
9
11
  }NODE;
12
+ /* メンバright,leftにNULLポインタがセットされているときは該当する子がいないことを表す */
10
13
 
11
14
  /* 初期状態では二分探索木は空の状態。
12
15
  グローバル変数rootが二分探索木の根へのポインタを保持しているものとする */
@@ -20,55 +23,88 @@
20
23
  /* fprintf関数を使ってstderrで標準エラーを出力する*/
21
24
  fprintf(stderr,"%s", s);
22
25
  exit(1); /* 異常終了 */
23
-
24
26
  }
25
27
 
28
+ /* 二分探索木から最小の要素を削除する関数 */
29
+ /* 削除した節へのポインタを返す
30
+ p:二分探索木へのポインタへのポインタ
31
+ (つまり*pが木へのポインタとなる)
32
+ NODE型へのポインターが戻り値 */
33
+ NODE *deletemin(NODE **p)
34
+ {
35
+ NODE *x;
36
+
37
+ while ((*p)->left != NULL)
38
+ p=&(*p)->left;
39
+ x=*p;
40
+ *p=(*p)->right;
41
+ return x;
42
+ }
43
+
26
44
  /* 二分探索木を探索する関数 */
45
+ /* パラメータkeyを受け取ってポインタを返す関数として定義
46
+ key:探索すべきキーの値
47
+ 探索に成功した場合そのデータの節へのポインタを返す
48
+ NODE型へのポインターが戻り値 */
27
49
  NODE *search(int key)
28
50
  {
29
51
  NODE *p; /* 現在注目している節 */
30
52
  p=root; /* まず根に注目する */
53
+
31
54
  /* 進むべき子が存在する限り繰り返す */
32
55
  while (p != NULL) {
33
56
  /* キーと注目している節のデータが等しいか比較 */
34
- if (key == p->data)
57
+ if (key == p->data){
35
58
  /* もしキーと注目している節のデータとが等しければポインタを関数として返す */
36
- printf("探索した値の番地です>>%d\n",p->data);
59
+ printf("探索した値の番地です>>%d\n",p);
37
60
  return p;
61
+ }else{
38
- else if (key < (p->data)) {
62
+ if (key < p->data)
39
63
  /* キーの方が小さければ左部分木に進む */
40
64
  p = p->left;
41
65
  else
42
66
  /* キーの方が大きければ右部分木に進む*/
43
67
  p = p->right;
44
68
  }
69
+ }
70
+ /* ループを抜け出たということは見付からなかったというと
71
+ NULL返して失敗したことを知らせる */
45
- printf("NotExist\n");
72
+ printf("NotExist\n");
46
73
  return NULL;
47
74
  }
48
75
 
49
76
  /* 二分探索木から要素を追加する関数*/
77
+ /* 探索と同じ要領で木を辿り、辿るべき部分木がなければそこに挿入する */
78
+ /* 挿入した要素が置かれる節へのポインタを返す
79
+ すでに要素が登録されているのなら、何もしないでNULLを返す
80
+ key:挿入するデータ
81
+ NODE型へのポインターが戻り値 */
50
82
  NODE *insert(int key)
51
83
  {
52
- int key;
53
84
  NODE **p,*new;
54
85
  /* 変数pが変数rootを指すように初期化する */
55
86
  p=&root;
56
87
  /* 挿入すべき場所が見つかるまで繰り返す */
57
88
  while (*p != NULL) {
58
89
  /* キーと注目している節のデータが等しいか比較 */
59
- if (key == (*p)->data)
90
+ if (key == (*p)->data){
60
91
  /* すでに登録されている */
92
+ printf("AlreadyExsits\n");
61
- return NULL;
93
+ return NULL;
94
+ }else{
62
- else if (key < (*p)->data) {
95
+ if (key < (*p)->data)
63
96
  /* キーの方が小さければ左部分木に進む */
64
97
  p =&(*p)->left;
65
98
  else
66
99
  /* キーの方が大きければ右部分木に進む */
67
100
  p =&(*p)->right;
68
101
  }
102
+ }
69
103
  /* 挿入されるべき場所が見つかったら */
70
104
  /* 挿入される節をつくる */
105
+
106
+ /* strct型のメモリを確保した分だけnewに入れる。もしNULLだったらエラー */
71
- if((new=malloc(sizeof(NODE)))=NULL)
107
+ if((new=malloc(sizeof(NODE)))==NULL)
72
108
  fatal_error("out of memory!!");
73
109
  /* 新しい節には子がないのでNULLにしておく */
74
110
  new->left =NULL;
@@ -79,12 +115,13 @@
79
115
  /* ポインタpは挿入される節へのポインタが入っている場所を指している */
80
116
  *p=new;
81
117
  return new;
82
- }
118
+ }
83
119
 
84
120
  /* 二分探索木から要素を削除する関数 */
121
+ /* 削除に成功したら1、要素が存在しなければ0を返す
122
+ key:削除するデータ */
85
123
  int delete(int key)
86
124
  {
87
- int key;
88
125
  /* 親へのポインタを使う */
89
126
  NODE **p,*x;
90
127
  /* 変数pが変数rootを指すように初期化する */
@@ -94,55 +131,46 @@
94
131
  /* 見つかった
95
132
  変数pは削除される節の親のメンバleft,right
96
133
  変数xは削除される節そのものを指している */
97
- if (key == (*p)->data){
134
+ if (key == (*p)->data){  
98
135
  x=*p;
99
136
  /* 1つも子を持っていない、葉である場合 */
100
- if(x->left==NULL && x->right==NULL)
137
+ if(x->left==NULL && x->right==NULL){    
101
138
  *p=NULL;
102
139
  /* 右の子のみをもつ */
103
- else if (x->left==NULL)
140
+ if(x->left==NULL){  //ここからif文の書き方変えました
104
141
  *p=x->right;
105
142
  /* 左の子のみをもつ */
106
- else if (x->right==NULL)
143
+ }else if(x->right==NULL){
107
144
  *p=x->left;
108
145
  /* 左右2つの子を持つ */
109
- else{
146
+ }else{
110
147
  /* 部分木から最小の要素を取り去る */
111
148
  *p=deletemin(&x->right);
112
- &(*p)->right=x->right;
149
+ (*p)->right=x->right;
113
- &(*p)->left=x->left;
150
+ (*p)->left=x->left;
114
151
  }
115
152
  /* 取り除いた節を解放させる */
116
153
  free(x);
117
154
  printf("Done\n");
118
155
  return 1;
156
+
119
157
  }else if(key < (*p)->data)
120
158
  /* 左部分木に進む */
121
159
  p=&(*p)->left;
122
160
  else
123
161
  /* 右部分木に進む */
124
162
  p=&(*p)->right;
163
+ }
125
164
  }
126
165
  /* 削除対象が見つからなかった */
127
166
  printf("NotExist\n");
128
167
  return 0;
129
168
  }
130
169
 
131
- /* 二分探索木から最小の要素を削除する関数 */
132
170
 
133
- NODE *deletemin(NODE **p)
134
- {
135
- NODE *x;
136
-
137
- while ((*p)->left != NULL)
138
- p=&(*p)->left;
139
- x=*p;
140
- *p=(*p)->right;
141
- return x;
142
- }
143
171
 
144
172
  /* 二分木を行きがけ順でなぞる */
145
- preorder(NODE *p)
173
+ void preorder(NODE *p)
146
174
  {
147
175
  /* 木が空なら何もしない */
148
176
  if(p==NULL)
@@ -151,42 +179,58 @@
151
179
  printf("%d",p->data); /* 自身の値を出力 */
152
180
  preorder(p->left); /* 左ノードへ移動 */
153
181
  preorder(p->right); /* 右ノードへ移動 */
182
+ }
154
183
  }
155
- }
156
184
 
157
185
  /* 二分木を通りがけ順でなぞる */
158
-
186
+ /* 全要素を昇順に表示する関数
187
+ 二分探索木の全要素を小→大の順で表示する */
188
+ /* 全体の流れ
189
+ ある要素の左枝先を全部調べ終えたら、自身の値を出力し、
190
+ 次にその要素の右枝先の要素を全部調べる
191
+ 左枝を調べる
192
+ 調べ終えたら戻ってくる
193
+ 値を出力する
194
+ 右枝を調べる
195
+ 調べ終えたら戻ってくる
196
+ 関数を終了して、自身を呼び出した関数の元へと戻る */
159
- inorder(NODE *p)
197
+ void inorder(NODE *p)
160
198
  {
161
199
  /* 木が空なら何もしない */
162
200
  if(p==NULL)
163
201
  return;
164
202
  else{
203
+ /* 引数に左へのポインタを渡すことで、再帰を繰り返して延々と左枝へ移動し
204
+ 一番左、一番小さい値にたどり着く
205
+ 子ノードはないため、引数の値はNULLに当たって戻ってくる
206
+ 一番下位の要素なので、左枝と同様に右枝もない。
207
+ なので終点である NULL に行き当たり、また return で戻ってくる。
208
+ そして「一番左を操作する関数」は処理を終える。
209
+ この関数に戻り値はない。「画面に出力」して、それで終了*/
165
210
  inorder(p->left); /* 左ノードへ移動 */
166
211
  printf("%d",p->data); /* 自身の値を出力 */
167
212
  inorder(p->right); /* 右ノードへ移動 */
168
213
  }
214
+ /* 関数を終了して、自身を呼び出した関数のもとへ戻る */
169
215
  }
170
216
 
171
217
  /* 二分木を帰りがけ順でなぞる */
172
- postorder(NODE *p)
218
+ void postorder(NODE *p)
173
219
  {
174
220
  /* 木が空なら何もしない */
175
221
  if(p==NULL)
176
222
  return;
177
223
  else{
178
- postorderr(p->left); /* 左ノードへ移動 */
224
+ postorder(p->left); /* 左ノードへ移動 */
179
225
  postorder(p->right); /* 右ノードへ移動 */
180
226
  printf("%d",p->data); /* 自身の値を出力 */
227
+ }
181
228
  }
182
- }
183
229
 
184
230
 
185
231
  int main(void)
186
- {
232
+ {
187
- int i;
188
- int n;
189
- int a,b,c;
233
+ int a,key1,key2;
190
234
  int mn=0;
191
235
 
192
236
  printf("二分探索木をします\n");
@@ -204,27 +248,29 @@
204
248
 
205
249
  case 2:
206
250
  printf("行きがけ順です\n");
207
- preorder();
251
+ preorder(root);
208
252
  break;
209
253
 
210
254
  case 3:
211
255
  printf("通りがけ順です\n");
212
- inorder();
256
+ inorder(root);
213
257
  break;
214
258
 
215
259
  case 4:
216
260
  printf("帰りがけ順です\n");
217
- postorder();
261
+ postorder(root);
218
262
  break;
219
263
 
220
264
  case 5:
221
265
  printf("指定した値の番地を出力します\n");
266
+ scanf("%d",&key1);
222
- search(key);
267
+ search(key1);
223
268
  break;
224
269
 
225
270
  case 6:
226
271
  printf("指定した値を削除します\n");
272
+ scanf("%d",&key2);
227
- delete(key);
273
+ delete(key2);
228
274
  break;
229
275
 
230
276
  case 9:
@@ -238,9 +284,7 @@
238
284
 
239
285
  return 0;
240
286
  }
241
- ここに言語を入力
242
- コード
243
- ```
287
+ ``
244
288
  ```### 前提・実現したいこと``````
245
289
  二分探索木のプログラムを実装したいです
246
290
  仕様は

8

直しました

2020/12/02 02:27

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -1,6 +1,6 @@
1
1
  ```
2
2
  `#include <stdio.h>
3
-
3
+ #include <stdlib.h>
4
4
  /* 木の節の定義 */
5
5
  typedef struct node{
6
6
  int data; /* 探索のキーになるデータ型 */

7

ミスを直しました

2020/12/01 09:34

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -152,6 +152,7 @@
152
152
  preorder(p->left); /* 左ノードへ移動 */
153
153
  preorder(p->right); /* 右ノードへ移動 */
154
154
  }
155
+ }
155
156
 
156
157
  /* 二分木を通りがけ順でなぞる */
157
158
 
@@ -178,6 +179,7 @@
178
179
  postorder(p->right); /* 右ノードへ移動 */
179
180
  printf("%d",p->data); /* 自身の値を出力 */
180
181
  }
182
+ }
181
183
 
182
184
 
183
185
  int main(void)

6

2020/12/01 09:23

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
File without changes

5

2020/12/01 09:20

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -258,8 +258,6 @@
258
258
  「34行目」で記述エラーを発見しました。
259
259
  「identifier」を付け忘れています。
260
260
  と出てしまいます
261
- 恐らくkeyの宣言の仕方がおかしいと思われます。
262
- 他にも凡ミスがあるかもしれません
263
261
  ```
264
262
 
265
263
  ### 該当のソースコード

4

2020/12/01 09:20

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -13,7 +13,7 @@
13
13
  /* グローバル変数rootをNULLで初期化 */
14
14
  NODE *root = NULL;
15
15
 
16
- * エラーメッセージをプリントしてexitする関数*/
16
+ /* エラーメッセージをプリントしてexitする関数*/
17
17
  /* ポインタ(アドレス)の先のデータを読み取り専用にする */
18
18
  void fatal_error(const char *s)
19
19
  {

3

ミスがあったので直しました

2020/12/01 09:19

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -6,7 +6,6 @@
6
6
  int data; /* 探索のキーになるデータ型 */
7
7
  struct node *left; /* 左の子 */
8
8
  struct node *right; /* 右の子 */
9
- char label; /* この節のラベル */
10
9
  }NODE;
11
10
 
12
11
  /* 初期状態では二分探索木は空の状態。
@@ -14,11 +13,19 @@
14
13
  /* グローバル変数rootをNULLで初期化 */
15
14
  NODE *root = NULL;
16
15
 
16
+ * エラーメッセージをプリントしてexitする関数*/
17
+ /* ポインタ(アドレス)の先のデータを読み取り専用にする */
18
+ void fatal_error(const char *s)
19
+ {
20
+ /* fprintf関数を使ってstderrで標準エラーを出力する*/
21
+ fprintf(stderr,"%s", s);
22
+ exit(1); /* 異常終了 */
23
+
24
+ }
17
25
 
18
26
  /* 二分探索木を探索する関数 */
19
27
  NODE *search(int key)
20
28
  {
21
- struct node key;
22
29
  NODE *p; /* 現在注目している節 */
23
30
  p=root; /* まず根に注目する */
24
31
  /* 進むべき子が存在する限り繰り返す */
@@ -62,7 +69,7 @@
62
69
  /* 挿入されるべき場所が見つかったら */
63
70
  /* 挿入される節をつくる */
64
71
  if((new=malloc(sizeof(NODE)))=NULL)
65
- error("out of memory!!");
72
+ fatal_error("out of memory!!");
66
73
  /* 新しい節には子がないのでNULLにしておく */
67
74
  new->left =NULL;
68
75
  new->right=NULL;
@@ -265,16 +272,77 @@
265
272
 
266
273
 
267
274
 
268
- ### 試したこと
275
+ ### 悩んでいること
269
- int key
276
+ まず、
270
- struct node key
277
+ NODE *search(int key)
271
- 宣言するか、よく分かっていません
278
+ 教科書に書いてあったこの宣言の仕方がよく分かません
272
- また、教科書を参考にして課題をするのでダブルポインタなどをそのまま使っています
273
279
 
280
+ 型名なしの関数の宣言の仕方を調べると一つだけ解説しているサイトが見つかり、自動的にint型になると書  いてあったのですが正しいのでしょうか?
274
281
 
282
+ 引数があり、戻り値がある場合はvoid型ではない、
283
+ 引数があり、戻り値がない場合はvoid型、
284
+ 引数がなし、戻り値がある場合もvoid型、
285
+ 引数がなし、戻り値がない場合もvoid型
286
+ と学びました
287
+
288
+ preorder(NODE *p)
289
+ postorder(NODE *p)
290
+ inorder(NODE *p)
291
+ これらの関数は引数があり、戻り値がない場合なのでvoid型、
292
+
293
+ int delete(int key)
294
+ この関数も引数があり、戻り値がない場合なのでvoid型だと思われるのですがなぜint型なのでしょうか
295
+
296
+ NODE *search(int key)
297
+ NODE *insert(int key)
298
+ NODE *deletemin(NODE **p)
299
+ これらの関数は引数があり、戻り値がある場合はvoid型ではない、int型だと思います。
300
+
301
+ ②keyの扱い方についてです
302
+
303
+ if (key == p->data)
304
+ ここの部分で教科書では関数を使って比べていましたがむずかしいので不等号を使って比べることにしました
305
+ keyは値ですが、p->dataは番地ですよね
306
+ 同じように値同士で扱うにはどのようにしたら良いのでしょうか
307
+ 構造体の場合、アロー演算子は番地、ドットが実体だと習いましたがエラーが出てしまいます
308
+
309
+
310
+ ③関数の値渡しについてです
311
+ case 1:
312
+ printf("追加する数字を入力してください\n");
313
+ scanf("%d",&a);
314
+ insert(a);
315
+ break;
316
+ case 5:
317
+ printf("指定した値の番地を出力します\n");
318
+ scanf("%d",&key1);
319
+ search(key1);
320
+ break;
321
+
322
+ case 6:
323
+ printf("指定した値を削除します\n");
324
+ scanf("%d",&key2);
325
+ delete(key2);
326
+ break;
327
+
328
+ ここの部分で出力する場合の値と指定した値の変数名はそれぞれ変えたほうが良いですよね?
329
+
330
+ ④探索した値の番地を出力する際に、
331
+
332
+ /* もしキーと注目している節のデータとが等しければポインタを関数として返す */
333
+ printf("探索した値の番地です>>%d\n",p->data);
334
+ return p;
335
+
336
+ としていますが、めちゃくちゃな状態です
337
+ 探索した値の番地を返す場合、 return pはどのように扱えば良いのか悩みます。
338
+
339
+
340
+
341
+
342
+
275
343
  ### 補足情報(FW/ツールのバージョンなど
276
344
 
277
345
  初心者で使い方がよく分かっていません
346
+ 自分の理解が正しいのか不安なのでコメント多いです
347
+ 見づらければ修正します
278
- ご指摘ください
348
+ ご指摘ください
279
-
280
- コードの挿入の仕方がよく分かっていません

2

コードの挿入ができたと思います

2020/12/01 09:16

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -1,3 +1,4 @@
1
+ ```
1
2
  `#include <stdio.h>
2
3
 
3
4
  /* 木の節の定義 */
@@ -228,7 +229,7 @@
228
229
 
229
230
  return 0;
230
231
  }
231
- ``ここに言語を入力
232
+ ここに言語を入力
232
233
  コード
233
234
  ```
234
235
  ```### 前提・実現したいこと``````
@@ -276,4 +277,4 @@
276
277
  初心者で使い方がよく分かっていません
277
278
  ご指摘ください
278
279
 
279
- コードの挿入の仕方は合っていますでしょうか????
280
+ コードの挿入の仕方がよく分かっていません

1

コードの挿入の仕方は合っていますでしょうか????

2020/12/01 03:28

投稿

kyapi
kyapi

スコア5

title CHANGED
File without changes
body CHANGED
@@ -1,29 +1,5 @@
1
- ### 前提・実現したいこと
2
- 二分探索木のプログラムを実装したいです
1
+ `#include <stdio.h>
3
- 仕様は
4
- 数字を入力して
5
- 1=追加
6
- 2=行きがけ順で表示
7
- 3=通りがけ順で表示
8
- 4=帰りがけ順で表示
9
- 5=指定した値の番地で表示
10
- 6=削除
11
- 9=終了
12
- ができるようにしたいです
13
- アドバイスお願いいたします!!
14
2
 
15
- ### 発生している問題・エラーメッセージ
16
-
17
- 「34行目」で記述エラーを発見しました。
18
- 「identifier」を付け忘れています。
19
- と出てしまいます
20
- 恐らくkeyの宣言の仕方がおかしいと思われます。
21
- 他にも凡ミスがあるかもしれません
22
- ```
23
-
24
- ### 該当のソースコード
25
- #include <stdio.h>
26
-
27
3
  /* 木の節の定義 */
28
4
  typedef struct node{
29
5
  int data; /* 探索のキーになるデータ型 */
@@ -252,9 +228,38 @@
252
228
 
253
229
  return 0;
254
230
  }
231
+ ``ここに言語を入力
232
+ コード
233
+ ```
234
+ ```### 前提・実現したいこと``````
235
+ 二分探索木のプログラムを実装したいです
236
+ 仕様は
237
+ 数字を入力して
238
+ 1=追加
239
+ 2=行きがけ順で表示
240
+ 3=通りがけ順で表示
241
+ 4=帰りがけ順で表示
242
+ 5=指定した値の番地で表示
243
+ 6=削除
244
+ 9=終了
245
+ ができるようにしたいです
246
+ アドバイスお願いいたします!!
255
247
 
248
+ ### 発生している問題・エラーメッセージ
256
249
 
250
+ 「34行目」で記述エラーを発見しました。
251
+ 「identifier」を付け忘れています。
252
+ と出てしまいます
253
+ 恐らくkeyの宣言の仕方がおかしいと思われます。
254
+ 他にも凡ミスがあるかもしれません
255
+ ```
257
256
 
257
+ ### 該当のソースコード
258
+ ``````ここに言語を入力
259
+ ここに言語を入力
260
+ ```
261
+ コード
262
+ ```
258
263
 
259
264
 
260
265
 
@@ -266,6 +271,9 @@
266
271
  また、教科書を参考にして課題をするのでダブルポインタなどをそのまま使っています
267
272
 
268
273
 
269
- ### 補足情報(FW/ツールのバージョンなど
274
+ ### 補足情報(FW/ツールのバージョンなど
270
275
 
271
- ここにり詳細な情報を記載してださ
276
+ 初心者で使い方がよく分かってません
277
+ ご指摘ください
278
+
279
+ コードの挿入の仕方は合っていますでしょうか????