質問編集履歴

18

aasdsad

2017/12/10 13:44

投稿

退会済みユーザー
test CHANGED
@@ -1 +1 @@
1
- C言語プログラミングの二分木と再帰法と動的計画法を使って解く問題に関する質問です。
1
+ aaC言語プログラミングの二分木と再帰法と動的計画法を使って解く問題に関する質問です。
test CHANGED
@@ -1,169 +1 @@
1
- C言語プログラミングの質問です。
2
-
3
-
4
-
5
- ーーーーーーーーーーーー問題文ーーーーーーーーーーーーーーー
6
-
7
-
8
-
9
- 京都では毎年八月十六日に五山の送り火が行
10
-
11
- われる. この日には, 五つの異なる形をした大き
12
-
13
- な焚き火が京都の山々でたかれる. この五つの
14
-
15
- 形には「大文字」, 「法・妙」, 「舟形」, 「左
16
-
17
- 大文字」, 「鳥居形」があり, 伝統的にこの順番
18
-
19
- で点火される.
20
-
21
- 京都はまた, 通りが長方形の格子状になるよ
22
-
23
- うに構築されている. それぞれの送り火の位置
24
-
25
- が, 以下に示すように二つの通りの交差上にあ
26
-
27
- るとする:
28
-
29
- 1. 大文字: 今出川通と白川通,
30
-
31
- 2. 法・妙: 北山通と下鴨本通(河原町通),
32
-
33
- 3. 舟形: 宝ヶ池通と千本通,
34
-
35
- 4. 左大文字: 北大路通と大宮通,
36
-
37
- 5. 鳥居形: 今出川通と西大路通,
38
-
39
- また, 自身が二つの通りのどちらかに居れば, 送
40
-
41
- り火を見ることができるとする.
42
-
43
-
44
-
45
- 一区画歩くのに五分かかるとし, 現在京都大
46
-
47
- 学吉田キャンパスにいるとする. 吉田キャンパ
48
-
49
- スは今出川通と東大路通の交差上にある. 今送
50
-
51
- り火が始まったとすると, 大文字の送り火は現
52
-
53
- 在の場所からちょうど見られる. しかし, 法・妙
54
-
55
- の送り火が始まると, 西の河原町通へ移動する
56
-
57
- ために十分かけて二区画歩くか, もしくは北の
58
-
59
- 北山通へ二十分かけて四区画歩く必要がある.
60
-
61
- ここで, 三つ目の舟形の送り火が宝ヶ池通と千
62
-
63
- 本通で始まるとどうなるだろうか. もし西へ向
64
-
65
- かうことを選んでおり, 今出川通と河原町通に
66
-
67
- いるのであれば, 西に三区画の千本通に向かう
68
-
69
- か, あるいは北に五区画の宝ヶ池通に向かうか
70
-
71
- を選ぶことができる. しかし, すでに東大路通
72
-
73
- と北山通にいるのであれば, 西に五区画の千本
74
-
75
- 通へ向かうか, あるいは北にたった一区画の宝ヶ
76
-
77
- 池通に向かうかを選ぶことができる.
78
-
79
- さて, 送り火を全て見るために歩くのに五分かかる
80
-
81
- 最短時間はいくらかであろうか.
82
-
83
-
84
-
85
- この問題を一般化すると以下のようになる。
86
-
87
-
88
-
89
- 今, ある自然数k に対して[-k, k] に座標を持つ
90
-
91
- ような, (2k + 1) × (2k + 1) の正方格子の原点
92
-
93
- (0,0) に居るとする. この格子の一区画を歩くの
94
-
95
- に1 単位時間かかる. ある順番でn 個の座標ペ
96
-
97
- ア(送り火の位置、iは順番)(x[i],y[i]), -k <= x[i],y[i] <= k(i = 1,2,...,n) が
98
-
99
- 与えられ, 全ての送り火を与えられた順番で見
100
-
101
- たい。また、送り火の位置が(x,y)とすると、(x,all)または(all,y)(allは-k <= all
1
+ aasmdmlasmdlma_sldmas_;mdlalsmd;lasdmsadlams;mdlsam;ldm;asm;dm;asmdm;lasdm;asdm;alsmdlasmd;mlasmdasdasd
102
-
103
- <= kを満たす任意の整数)に行けば送り火を見られるとする。
104
-
105
-
106
-
107
- この問題を動的計画法で解け。
108
-
109
-
110
-
111
-
112
-
113
- ーーーーーーーーーーーーーーーーーーーーー
114
-
115
-
116
-
117
- 入力形式はテキストファイルinput.txtに入っていて、入力形式は
118
-
119
- n
120
-
121
- k
122
-
123
- x[1] y[1]
124
-
125
- x[2] y[2]
126
-
127
- ・ ・
128
-
129
- ・ ・
130
-
131
- ・ ・
132
-
133
- x[n] y[n]
134
-
135
- です。
136
-
137
- ちなみに入力はうまくできました。
138
-
139
-
140
-
141
-
142
-
143
- この問題を二分木を使って解きたいんですが、アルゴリズムがわからないので教えて欲しいです。今思いついた解き方について少しして説明します。
144
-
145
- まず漸化式を以下のように決めました。
146
-
147
- (a[i],b[i])を (x[i],y[i]) が見える最短の位置とする。||は絶対値です。
148
-
149
-
150
-
151
- |x[i] - a[i-1]| < |y[i] - b[i-1]|の時
152
-
153
-     (a[i],b[i]) = (x[i],b[i-1])
154
-
155
-
156
-
157
- |x[i] - a[i-1]| < |y[i] - b[i-1]|の時
158
-
159
-     (a[i],b[i]) = (a[i-1],y[i])
160
-
161
-
162
-
163
- |x[i] - a[i-1]| = |y[i] - b[i-1]|の時
164
-
165
-      最短路が二つできるから、ここで二分木を使うのかと思われるが実装方法がわからない。
166
-
167
-
168
-
169
- アルゴリズムを教えて欲しいです。

17

説明の変更。

2017/12/10 13:44

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -104,7 +104,7 @@
104
104
 
105
105
 
106
106
 
107
- この問題を再帰法と動的計画法、二つのやり方で解け。
107
+ この問題を動的計画法で解け。
108
108
 
109
109
 
110
110
 
@@ -140,9 +140,9 @@
140
140
 
141
141
 
142
142
 
143
- この問題を再帰法と二分木を使ってC言語で解きたくて、書てみたんですが、実装方法がわからないところがあります。解き方について少しして説明します。
143
+ この問題を二分木を使って解きたいんですが、アルゴリズムがわからないので教えて欲しいです。今思いついた解き方について少しして説明します。
144
144
 
145
- まず再帰の漸化式を以下のように決めました。
145
+ まず漸化式を以下のように決めました。
146
146
 
147
147
  (a[i],b[i])を (x[i],y[i]) が見える最短の位置とする。||は絶対値です。
148
148
 
@@ -166,368 +166,4 @@
166
166
 
167
167
 
168
168
 
169
- ちなみに未完成のソースコードはこちらです。(未完成であり、間違った結果を出力してしまっているので、実装方法がわかる聡明な方は、お読みにならないことをお勧めします。)funcという二分木と再帰を用いて(a[i],b[i])までの最短路を求める関数の実装方法がわかりません。再帰呼び出しの位置がが違うのだと思いますが、どこで呼び出せばいいのかもわかりません。
170
-
171
-
172
-
173
- ```C言語
174
-
175
- #include<stdio.h>
176
-
177
- #include<stdlib.h>
178
-
179
-
180
-
181
- struct node {
182
-
183
- int value;// このノードが保持している値
184
-
185
- int length;// 最短路の長さ
186
-
187
- struct node *left_ptr; // 左枝
188
-
189
- struct node *right_ptr; // 右枝
190
-
191
- };
192
-
193
- // ツリーの頂点 root
194
-
195
- static struct node *root = NULL;
196
-
197
-
198
-
199
- int x[100]; //送り火の位置のx座標
200
-
201
- int y[100]; //送り火の位置のy座標
202
-
203
- int count = 1; //データ入力のための変数
204
-
205
-
206
-
207
- void print_tree(struct node *);
208
-
209
- void find_shortest_path(int,int*,int*,int*); //最短路を求める再帰関数
210
-
211
- void make_tree(struct node **node,int value,int length); //二分木を作る関数
212
-
213
- int main(){
214
-
215
-
216
-
217
- //
218
-
219
- //データの入力
220
-
221
- //
222
-
223
- int input[100];
224
-
225
- int ret;
226
-
227
- int a,b;
228
-
229
-
230
-
231
- FILE *file;
232
-
233
- file = fopen("input.txt","r");
234
-
235
- if(file == NULL) {
236
-
237
- printf("the file can`t be opened\n");
238
-
239
- return -1;
240
-
241
- }
242
-
243
- int m = 0;
244
-
245
- while(( ret = fscanf( file , "%d %d" , &a , &b )) != EOF ) {
246
-
247
- input[m] = a;
248
-
249
- m++;
250
-
251
- input[m] = b;
252
-
253
- m++;
254
-
255
- }
256
-
257
- fclose(file);
258
-
259
- // end input
260
-
261
-
262
-
263
- int n = input[0];// 送り火の数(n)
264
-
265
- int k = input[1];// (2k+1)x(2k+1)の格子のサイズ
266
-
267
- int now_x,now_y = 0; //現在の位置
268
-
269
-
270
-
271
- //送り火の位置の入力
272
-
273
- for(int v = 2; v < m; v++){
274
-
275
- if(v % 2 == 0){
276
-
277
- x[v / 2] = input[v];
278
-
279
- }else{
280
-
281
- y[ (v-1)/2 ] = input[v];
282
-
283
- }
284
-
285
- }
286
-
287
- //
288
-
289
- //データの入力終了
290
-
291
- //
292
-
293
-
294
-
295
-
296
-
297
- //データを出力
298
-
299
- printf("n = %d,k = %d\n",n,k);
300
-
301
- for(int v = 1; v < n+1; v++){
302
-
303
- printf("(x[%d],y[%d]) = (%d,%d)\n",v,v,x[v],y[v]);
304
-
305
- }
306
-
307
-
308
-
309
-
310
-
311
- int address1 = 1; //アドレスを確保するための適当な値
312
-
313
- int address2 = 2;
314
-
315
- int address3 = 3;
316
-
317
- find_shortest_path(n,&address1,&address2,&address3);
318
-
319
-
320
-
321
- print_tree(root);
322
-
323
-
324
-
325
- return 0;
326
-
327
- }
328
-
329
-
330
-
331
-
332
-
333
- //*l は(x[n],y[n])が見える最短路の長さ
334
-
335
- //(*a,*b)は(x[n],y[n])が見える最短の位置
336
-
337
- //
338
-
339
- void find_shortest_path(int n ,int *a,int *b,int *l){
340
-
341
- if(n != 0){
342
-
343
- find_shortest_path(n-1,a,b,l);
344
-
345
- int pre_a = *a;
346
-
347
- int pre_b = *b;
348
-
349
- int pre_l = *l;
350
-
351
-
352
-
353
-
354
-
355
- //if(abs(x[n] - pre_a) < abs(y[n]- pre_b)){
356
-
357
- *a = x[n];
358
-
359
- *b = pre_b;
360
-
361
- *l = *l + abs(x[n] - pre_a);
362
-
363
- printf("r\n");
364
-
365
- make_tree(&root->right_ptr,count,*l);
366
-
367
- count++;
368
-
369
-
370
-
371
- *l = pre_l;
372
-
373
- //}else if (abs(x[n] - pre_a) > abs(y[n]- pre_b)){
374
-
375
- *a = pre_a;
376
-
377
- *b = y[n];
378
-
379
- *l = *l + abs(y[n] - pre_b);
380
-
381
- printf("l\n");
382
-
383
- make_tree(&root->left_ptr,count,*l);
384
-
385
- count++;
386
-
387
- //}
388
-
389
-
390
-
391
- }else{
392
-
393
- *a = 0;
394
-
395
- *b = 0;
396
-
397
- *l = 0;
398
-
399
- printf("0\n");
400
-
401
- make_tree(&root,count,*l);
402
-
403
- count++;
404
-
405
- }
406
-
407
- }
408
-
409
-
410
-
411
- //length は(x[n],y[n])が見える最短路の長さ
412
-
413
- void make_tree(struct node **node, int value,int length)
414
-
415
- {
416
-
417
- int result; // 数値の大小比較結果
418
-
419
-
420
-
421
- // ノードが存在しない場合
422
-
423
- if ((*node) == NULL) {
424
-
425
-
426
-
427
- // 新しい領域を割り当てノードを作成する
428
-
429
- (*node) = malloc(sizeof(struct node));
430
-
431
- if ((*node) == NULL){
432
-
433
- fprintf(stderr, "NULL");
434
-
435
- exit (8);
436
-
437
- }
438
-
439
-
440
-
441
- // メンバを初期化
442
-
443
- (*node)->left_ptr = NULL;
444
-
445
- (*node)->right_ptr = NULL;
446
-
447
- (*node)->value = value;
448
-
449
- (*node)->length = length;
450
-
451
-
452
-
453
- // make_tree関数を終了
454
-
455
- return;
456
-
457
- }
458
-
459
-
460
-
461
- // 現在のノードより大きかったら正。小さかったら負。等しかったら0
462
-
463
- if ((*node)->value < value) {
464
-
465
- result = 1;
466
-
467
- } else if ((*node)->value > value) {
468
-
469
- result = -1;
470
-
471
- } else if ((*node)->value == value) {
472
-
473
- result = 0;
474
-
475
- }
476
-
477
-
478
-
479
- // 現在の数値が既にあれば、新たなノードは作成せずmake_tree関数を終了
480
-
481
- if (result == 0)
482
-
483
- return;
484
-
485
-
486
-
487
- // 大きかったら右枝に移動
488
-
489
- if (0 < result) {
490
-
491
- make_tree(&(*node)->right_ptr, value,length);
492
-
493
- }
494
-
495
- // 小さかったら左枝に移動
496
-
497
- else {
498
-
499
- make_tree(&(*node)->left_ptr, value,length);
500
-
501
- }
502
-
503
- }
504
-
505
-
506
-
507
- void print_tree(struct node *now)
508
-
509
- {
510
-
511
- if (now == NULL)
512
-
513
- return;
514
-
515
-
516
-
517
- print_tree(now->left_ptr);
518
-
519
- printf("%d %d\n",now->value,now->length);
520
-
521
- print_tree(now->right_ptr);
522
-
523
- }
524
-
525
-
526
-
527
-
528
-
529
- ```
530
-
531
-
532
-
533
- できれば動的計画法で解くアルゴリズム教えてくれるとありがたいです。
169
+ アルゴリズム教えて欲しいです。

16

説明の追加

2017/12/09 15:30

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -80,11 +80,13 @@
80
80
 
81
81
  最短時間はいくらかであろうか.
82
82
 
83
+
84
+
83
85
  この問題を一般化すると以下のようになる。
84
86
 
85
87
 
86
88
 
87
- 今, ある自然数k に対して[ k, k] に座標を持つ
89
+ 今, ある自然数k に対して[-k, k] に座標を持つ
88
90
 
89
91
  ような, (2k + 1) × (2k + 1) の正方格子の原点
90
92
 
@@ -92,11 +94,13 @@
92
94
 
93
95
  に1 単位時間かかる. ある順番でn 個の座標ペ
94
96
 
95
- ア(x[i],y[i]), -k <= x[i],y[i] <= k(i = 1,2,...,n) が
97
+ (送り火の位置、iは順番)(x[i],y[i]), -k <= x[i],y[i] <= k(i = 1,2,...,n) が
96
98
 
97
99
  与えられ, 全ての送り火を与えられた順番で見
98
100
 
101
+ たい。また、送り火の位置が(x,y)とすると、(x,all)または(all,y)(allは-k <= all
102
+
99
-
103
+ <= kを満す任意の整数)に行けば送り火を見られるとする
100
104
 
101
105
 
102
106
 

15

コード修正

2017/12/09 05:05

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -202,7 +202,7 @@
202
202
 
203
203
  void print_tree(struct node *);
204
204
 
205
- void func(int,int*,int*,int*); //最短路を求める再帰関数
205
+ void find_shortest_path(int,int*,int*,int*); //最短路を求める再帰関数
206
206
 
207
207
  void make_tree(struct node **node,int value,int length); //二分木を作る関数
208
208
 
@@ -310,7 +310,7 @@
310
310
 
311
311
  int address3 = 3;
312
312
 
313
- func(n,&address1,&address2,&address3);
313
+ find_shortest_path(n,&address1,&address2,&address3);
314
314
 
315
315
 
316
316
 
@@ -332,11 +332,11 @@
332
332
 
333
333
  //
334
334
 
335
- void func_find_shortest_path(int n ,int *a,int *b,int *l){
335
+ void find_shortest_path(int n ,int *a,int *b,int *l){
336
336
 
337
337
  if(n != 0){
338
338
 
339
- func_find_shortest_path(n-1,a,b,l);
339
+ find_shortest_path(n-1,a,b,l);
340
340
 
341
341
  int pre_a = *a;
342
342
 

14

追加の説明

2017/12/08 04:26

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -332,11 +332,11 @@
332
332
 
333
333
  //
334
334
 
335
- void func(int n ,int *a,int *b,int *l){
335
+ void func_find_shortest_path(int n ,int *a,int *b,int *l){
336
336
 
337
337
  if(n != 0){
338
338
 
339
- func(n-1,a,b,l);
339
+ func_find_shortest_path(n-1,a,b,l);
340
340
 
341
341
  int pre_a = *a;
342
342
 

13

追加の説明

2017/12/08 04:21

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -162,7 +162,7 @@
162
162
 
163
163
 
164
164
 
165
- ちなみに未完成のソースコードはこちらです。funcという二分木と再帰を用いて(a[i],b[i])までの最短路を求める関数の実装方法がわかりません。再帰呼び出しの位置がが違うのだと思いますが、どこで呼び出せばいいのかもわかりません。
165
+ ちなみに未完成のソースコードはこちらです。(未完成であり、間違った結果を出力してしまっているので、実装方法がわかる聡明な方は、お読みにならないことをお勧めします。)funcという二分木と再帰を用いて(a[i],b[i])までの最短路を求める関数の実装方法がわかりません。再帰呼び出しの位置がが違うのだと思いますが、どこで呼び出せばいいのかもわかりません。
166
166
 
167
167
 
168
168
 

12

追加の説明。

2017/12/08 04:19

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -162,7 +162,7 @@
162
162
 
163
163
 
164
164
 
165
- ちなみに未完成のソースコードはこちらです。funcという二分木と絡めた再帰を用いて最短路を求める実装方法がよくわかりません。
165
+ ちなみに未完成のソースコードはこちらです。funcという二分木と再帰を用いて(a[i],b[i])までの最短路を求める関数の実装方法がわかりません。再帰呼び出しの位置がが違うのだと思いますが、どこで呼び出せばいいのかもわかりません。
166
166
 
167
167
 
168
168
 

11

追加の説明

2017/12/08 04:17

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -162,7 +162,7 @@
162
162
 
163
163
 
164
164
 
165
- ちなみに未完成のソースコードはこちらです。funcという二分木と絡めた再帰関数の実装方法がよくわかりません。
165
+ ちなみに未完成のソースコードはこちらです。funcという二分木と絡めた再帰を用いて最短路を求める実装方法がよくわかりません。
166
166
 
167
167
 
168
168
 

10

説明の追加

2017/12/08 04:14

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -162,7 +162,7 @@
162
162
 
163
163
 
164
164
 
165
- ちなみに未完成のソースコードはこちらです。fという二分木と絡めた再帰関数の実装方法がよくわかりません。
165
+ ちなみに未完成のソースコードはこちらです。funcという二分木と絡めた再帰関数の実装方法がよくわかりません。
166
166
 
167
167
 
168
168
 

9

コードの編集

2017/12/08 04:12

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -200,7 +200,9 @@
200
200
 
201
201
 
202
202
 
203
+ void print_tree(struct node *);
204
+
203
- void f(int,int*,int*,int*); //最短路を求める再帰関数
205
+ void func(int,int*,int*,int*); //最短路を求める再帰関数
204
206
 
205
207
  void make_tree(struct node **node,int value,int length); //二分木を作る関数
206
208
 
@@ -302,19 +304,17 @@
302
304
 
303
305
 
304
306
 
305
- int p = 1; //アドレスを確保するための適当な値
307
+ int address1 = 1; //アドレスを確保するための適当な値
306
-
307
- int q = 2;
308
+
308
-
309
- int r = 20;
309
+ int address2 = 2;
310
+
310
-
311
+ int address3 = 3;
312
+
311
- f(n,&p,&q,&r);
313
+ func(n,&address1,&address2,&address3);
312
-
313
-
314
-
314
+
315
+
316
+
315
- //答えを出力
317
+ print_tree(root);
316
-
317
- printf("(x,y) = (%d %d), answer = %d\n",p,q,r);
318
318
 
319
319
 
320
320
 
@@ -326,77 +326,173 @@
326
326
 
327
327
 
328
328
 
329
- // *l は(x[n],y[n])が見える位置(a[n],b[n])に到るまでの路の長で最短路の長さ
329
+ //*l は(x[n],y[n])が見える最短路の長さ
330
-
330
+
331
- // (*a,*b) は(a[n],b[n])に対応す
331
+ //*a,*bは(x[n],y[n])が見え最短の位置
332
+
332
-
333
+ //
334
+
333
- void f(int n ,int *a,int *b,int *l){
335
+ void func(int n ,int *a,int *b,int *l){
334
336
 
335
337
  if(n != 0){
336
338
 
337
- f(n-1,a,b,l);
339
+ func(n-1,a,b,l);
338
-
340
+
339
- int pre_a = *a; //(a[n-1] , b[n-1]) = (pre_a,pre_b)
341
+ int pre_a = *a;
340
342
 
341
343
  int pre_b = *b;
342
344
 
343
345
  int pre_l = *l;
344
346
 
345
- if(abs(x[n] - pre_a) < abs(y[n]- pre_b)){
346
-
347
- *a = x[n]; //(a[n],b[n]) = (x[n],b[n-1])
348
-
349
- *b = pre_b;
350
-
351
- *l = *l + abs(x[n] - pre_a);
352
-
353
- }else if (abs(x[n] - pre_a) > abs(y[n]- pre_b)){
354
-
355
- *a = pre_a; //(a[n],b[n]) = (a[n-1],y[n])
356
-
357
- *b = y[n];
358
-
359
- *l = *l + abs(y[n] - pre_b);
360
-
361
- }else{
362
-
363
-
364
-
365
- //(a[n-1],b[n-1])から(x[n],y[n])が見える位置、(a[n],b[n)同じだった時、分岐するのだが、ここの実装方法がわかリマセン。
366
-
367
- *a = x[n];
368
-
369
- *b = pre_b;
370
-
371
- *l = *l + abs(x[n] - pre_a);
372
-
373
- make_tree(root->right_ptr,count,*l);
374
-
375
- count++;
376
-
377
-
378
-
379
- *a = pre_a;
380
-
381
- *b = y[n];
382
-
383
- *l = *l + abs(y[n] - pre_b);
384
-
385
- make_tree(root->left_ptr,count,*l);
386
-
387
- count++;
347
+
348
+
349
+
350
+
351
+ //if(abs(x[n] - pre_a) < abs(y[n]- pre_b)){
352
+
353
+ *a = x[n];
354
+
355
+ *b = pre_b;
356
+
357
+ *l = *l + abs(x[n] - pre_a);
358
+
359
+ printf("r\n");
360
+
361
+ make_tree(&root->right_ptr,count,*l);
362
+
363
+ count++;
364
+
365
+
366
+
367
+ *l = pre_l;
368
+
369
+ //}else if (abs(x[n] - pre_a) > abs(y[n]- pre_b)){
370
+
371
+ *a = pre_a;
372
+
373
+ *b = y[n];
374
+
375
+ *l = *l + abs(y[n] - pre_b);
376
+
377
+ printf("l\n");
378
+
379
+ make_tree(&root->left_ptr,count,*l);
380
+
381
+ count++;
382
+
383
+ //}
384
+
385
+
386
+
387
+ }else{
388
+
389
+ *a = 0;
390
+
391
+ *b = 0;
392
+
393
+ *l = 0;
394
+
395
+ printf("0\n");
396
+
397
+ make_tree(&root,count,*l);
398
+
399
+ count++;
400
+
401
+ }
402
+
403
+ }
404
+
405
+
406
+
407
+ //length は(x[n],y[n])が見える最短路の長さ
408
+
409
+ void make_tree(struct node **node, int value,int length)
410
+
411
+ {
412
+
413
+ int result; // 数値の大小比較結果
414
+
415
+
416
+
417
+ // ノードが存在しない場合
418
+
419
+ if ((*node) == NULL) {
420
+
421
+
422
+
423
+ // 新しい領域を割り当てノードを作成する
424
+
425
+ (*node) = malloc(sizeof(struct node));
426
+
427
+ if ((*node) == NULL){
428
+
429
+ fprintf(stderr, "NULL");
430
+
431
+ exit (8);
388
432
 
389
433
  }
390
434
 
391
435
 
392
436
 
437
+ // メンバを初期化
438
+
439
+ (*node)->left_ptr = NULL;
440
+
441
+ (*node)->right_ptr = NULL;
442
+
443
+ (*node)->value = value;
444
+
445
+ (*node)->length = length;
446
+
447
+
448
+
449
+ // make_tree関数を終了
450
+
451
+ return;
452
+
453
+ }
454
+
455
+
456
+
457
+ // 現在のノードより大きかったら正。小さかったら負。等しかったら0
458
+
459
+ if ((*node)->value < value) {
460
+
461
+ result = 1;
462
+
463
+ } else if ((*node)->value > value) {
464
+
465
+ result = -1;
466
+
467
+ } else if ((*node)->value == value) {
468
+
469
+ result = 0;
470
+
471
+ }
472
+
473
+
474
+
475
+ // 現在の数値が既にあれば、新たなノードは作成せずmake_tree関数を終了
476
+
477
+ if (result == 0)
478
+
479
+ return;
480
+
481
+
482
+
483
+ // 大きかったら右枝に移動
484
+
485
+ if (0 < result) {
486
+
487
+ make_tree(&(*node)->right_ptr, value,length);
488
+
489
+ }
490
+
491
+ // 小さかったら左枝に移動
492
+
393
- }else{
493
+ else {
394
-
395
- *a = 0;
494
+
396
-
397
- *b = 0;
398
-
399
- *l = 0;
495
+ make_tree(&(*node)->left_ptr, value,length);
400
496
 
401
497
  }
402
498
 
@@ -404,97 +500,21 @@
404
500
 
405
501
 
406
502
 
407
- //length は(x[n],y[n])が見える最短路の長さ
408
-
409
- void make_tree(struct node **node, int value,int length)
503
+ void print_tree(struct node *now)
410
504
 
411
505
  {
412
506
 
413
- int result; // 数値の大小比較結果
414
-
415
-
416
-
417
- // ノードが存在しない場合
418
-
419
- if ((*node) == NULL) {
420
-
421
-
422
-
423
- // 新しい領域を割り当てノードを作成する
424
-
425
- (*node) = malloc(sizeof(struct node));
426
-
427
- if ((*node) == NULL){
507
+ if (now == NULL)
428
-
429
- fprintf(stderr, "NULL");
430
-
431
- exit (8);
432
-
433
- }
434
-
435
-
436
-
437
- // メンバを初期化
438
-
439
- (*node)->left_ptr = NULL;
440
-
441
- (*node)->right_ptr = NULL;
442
-
443
- (*node)->value = value;
444
-
445
- (*node)->length = length;
446
-
447
-
448
-
449
- // make_tree関数を終了
450
508
 
451
509
  return;
452
510
 
453
- }
511
+
454
-
455
-
456
-
457
- // 現在のノードより大きかったら正。小さかったら負。等しかったら0
512
+
458
-
459
- if ((*node)->value < value) {
513
+ print_tree(now->left_ptr);
460
-
461
- result = 1;
514
+
462
-
463
- } else if ((*node)->value > value) {
515
+ printf("%d %d\n",now->value,now->length);
464
-
465
- result = -1;
516
+
466
-
467
- } else if ((*node)->value == value) {
468
-
469
- result = 0;
470
-
471
- }
472
-
473
-
474
-
475
- // 現在の数値が既にあれば、新たなノードは作成せずmake_tree関数を終了
476
-
477
- if (result == 0)
478
-
479
- return;
480
-
481
-
482
-
483
- // 大きかったら右枝に移動
484
-
485
- if (0 < result) {
486
-
487
- make_tree(&(*node)->right_ptr, value,length);
517
+ print_tree(now->right_ptr);
488
-
489
- }
490
-
491
- // 小さかったら左枝に移動
492
-
493
- else {
494
-
495
- make_tree(&(*node)->left_ptr, value,length);
496
-
497
- }
498
518
 
499
519
  }
500
520
 

8

説明の追加

2017/12/08 04:07

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -142,14 +142,20 @@
142
142
 
143
143
  (a[i],b[i])を (x[i],y[i]) が見える最短の位置とする。||は絶対値です。
144
144
 
145
+
146
+
145
147
  |x[i] - a[i-1]| < |y[i] - b[i-1]|の時
146
148
 
147
149
      (a[i],b[i]) = (x[i],b[i-1])
148
150
 
151
+
152
+
149
153
  |x[i] - a[i-1]| < |y[i] - b[i-1]|の時
150
154
 
151
155
      (a[i],b[i]) = (a[i-1],y[i])
152
156
 
157
+
158
+
153
159
  |x[i] - a[i-1]| = |y[i] - b[i-1]|の時
154
160
 
155
161
       最短路が二つできるから、ここで二分木を使うのかと思われるが実装方法がわからない。
@@ -320,9 +326,7 @@
320
326
 
321
327
 
322
328
 
323
- // *l は(x[n],y[n])が見える最短路の長さ
329
+ // *l は(x[n],y[n])が見える位置(a[n],b[n])に到るまでの路の長で最短路の長さ
324
-
325
- // (a[n],b[n])は(x[n],y[n])が見える最短の位置とすると、
326
330
 
327
331
  // (*a,*b) は(a[n],b[n])に対応する。
328
332
 
@@ -340,13 +344,37 @@
340
344
 
341
345
  if(abs(x[n] - pre_a) < abs(y[n]- pre_b)){
342
346
 
347
+ *a = x[n]; //(a[n],b[n]) = (x[n],b[n-1])
348
+
349
+ *b = pre_b;
350
+
351
+ *l = *l + abs(x[n] - pre_a);
352
+
353
+ }else if (abs(x[n] - pre_a) > abs(y[n]- pre_b)){
354
+
355
+ *a = pre_a; //(a[n],b[n]) = (a[n-1],y[n])
356
+
357
+ *b = y[n];
358
+
359
+ *l = *l + abs(y[n] - pre_b);
360
+
361
+ }else{
362
+
363
+
364
+
365
+ //(a[n-1],b[n-1])から(x[n],y[n])が見える位置、(a[n],b[n)同じだった時、分岐するのだが、ここの実装方法がわかリマセン。
366
+
343
367
  *a = x[n];
344
368
 
345
369
  *b = pre_b;
346
370
 
347
371
  *l = *l + abs(x[n] - pre_a);
348
372
 
349
- }else if (abs(x[n] - pre_a) > abs(y[n]- pre_b)){
373
+ make_tree(root->right_ptr,count,*l);
374
+
375
+ count++;
376
+
377
+
350
378
 
351
379
  *a = pre_a;
352
380
 
@@ -354,34 +382,10 @@
354
382
 
355
383
  *l = *l + abs(y[n] - pre_b);
356
384
 
357
- }else{
358
-
359
-
360
-
361
- //(a[n-1],b[n-1])から(x[n],y[n])が見える位置、(a[n],b[n)同じだった時、分岐するのだが、ここの実装方法がわかリマセン。
362
-
363
- *a = x[n];
364
-
365
- *b = pre_b;
366
-
367
- *l = *l + abs(x[n] - pre_a);
368
-
369
- make_tree(root->right_ptr,count,*l);
385
+ make_tree(root->left_ptr,count,*l);
370
386
 
371
387
  count++;
372
388
 
373
-
374
-
375
- *a = pre_a;
376
-
377
- *b = y[n];
378
-
379
- *l = *l + abs(y[n] - pre_b);
380
-
381
- make_tree(root->left_ptr,count,*l);
382
-
383
- count++;
384
-
385
389
  }
386
390
 
387
391
 

7

説明の追加

2017/12/07 13:38

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -152,7 +152,7 @@
152
152
 
153
153
  |x[i] - a[i-1]| = |y[i] - b[i-1]|の時
154
154
 
155
-      最短路が二つできるここの扱いがわからない。
155
+      最短路が二つできるから、ここで二分木を使うかと思われる実装方法がわからない。
156
156
 
157
157
 
158
158
 

6

説明追加

2017/12/07 13:33

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
 
4
4
 
5
+ ーーーーーーーーーーーー問題文ーーーーーーーーーーーーーーー
6
+
7
+
8
+
5
9
  京都では毎年八月十六日に五山の送り火が行
6
10
 
7
11
  われる. この日には, 五つの異なる形をした大き
@@ -92,7 +96,17 @@
92
96
 
93
97
  与えられ, 全ての送り火を与えられた順番で見
94
98
 
95
- たい.
99
+ たい
100
+
101
+
102
+
103
+ この問題を再帰法と動的計画法、二つのやり方で解け。
104
+
105
+
106
+
107
+
108
+
109
+ ーーーーーーーーーーーーーーーーーーーーー
96
110
 
97
111
 
98
112
 

5

説明追加

2017/12/07 13:23

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -130,15 +130,15 @@
130
130
 
131
131
  |x[i] - a[i-1]| < |y[i] - b[i-1]|の時
132
132
 
133
- (a[i],b[i]) = (x[i],b[i-1])
133
+     (a[i],b[i]) = (x[i],b[i-1])
134
134
 
135
135
  |x[i] - a[i-1]| < |y[i] - b[i-1]|の時
136
136
 
137
- (a[i],b[i]) = (a[i-1],y[i)
137
+     (a[i],b[i]) = (a[i-1],y[i]
138
138
 
139
139
  |x[i] - a[i-1]| = |y[i] - b[i-1]|の時
140
140
 
141
- 最短路が二つできる。ここの扱いがわからない。
141
+      最短路が二つできる。ここの扱いがわからない。
142
142
 
143
143
 
144
144
 

4

説明追加

2017/12/07 13:21

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -126,7 +126,7 @@
126
126
 
127
127
  まず再帰の漸化式を以下のように決めました。
128
128
 
129
- (a[i],b[i])を (x[i],y[i]) が見える最短の位置とする。
129
+ (a[i],b[i])を (x[i],y[i]) が見える最短の位置とする。||は絶対値です。
130
130
 
131
131
  |x[i] - a[i-1]| < |y[i] - b[i-1]|の時
132
132
 

3

説明追加

2017/12/07 13:10

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -88,7 +88,7 @@
88
88
 
89
89
  に1 単位時間かかる. ある順番でn 個の座標ペ
90
90
 
91
- ア(xi,yi), -k <= xi,yi <= k(i = 1,2,...,n) が
91
+ ア(x[i],y[i]), -k <= x[i],y[i] <= k(i = 1,2,...,n) が
92
92
 
93
93
  与えられ, 全ての送り火を与えられた順番で見
94
94
 
@@ -102,9 +102,9 @@
102
102
 
103
103
  k
104
104
 
105
- x1 y1
105
+ x[1] y[1]
106
-
106
+
107
- x2 y2
107
+ x[2] y[2]
108
108
 
109
109
  ・ ・
110
110
 
@@ -112,22 +112,40 @@
112
112
 
113
113
  ・ ・
114
114
 
115
- xn yn
115
+ x[n] y[n]
116
+
116
-
117
+ です。
118
+
117
-
119
+ ちなみに入力はうまくできました。
118
-
119
-
120
-
121
-
122
-
120
+
121
+
122
+
123
+
124
+
123
- この問題を再帰法と二分木を使ってC言語できたいんですが、実装方法がわかりません
125
+ この問題を再帰法と二分木を使ってC言語できたくて、書てみたんですが、実装方法がわからないところがありま解き方について少しして説明します。
126
+
124
-
127
+ まず再帰の漸化式を以下のように決めました。
128
+
129
+ (a[i],b[i])を (x[i],y[i]) が見える最短の位置とする。
130
+
131
+ |x[i] - a[i-1]| < |y[i] - b[i-1]|の時
132
+
133
+ (a[i],b[i]) = (x[i],b[i-1])
134
+
135
+ |x[i] - a[i-1]| < |y[i] - b[i-1]|の時
136
+
137
+ (a[i],b[i]) = (a[i-1],y[i)
138
+
139
+ |x[i] - a[i-1]| = |y[i] - b[i-1]|の時
140
+
125
- できれば動的計画法で解く方法も教えてくれとありです
141
+ 最短路が二つできる。ここの扱いわからない。
126
142
 
127
143
 
128
144
 
129
145
  ちなみに未完成のソースコードはこちらです。fという二分木と絡めた再帰関数の実装方法がよくわかりません。
130
146
 
147
+
148
+
131
149
  ```C言語
132
150
 
133
151
  #include<stdio.h>
@@ -467,3 +485,7 @@
467
485
 
468
486
 
469
487
  ```
488
+
489
+
490
+
491
+ できれば動的計画法で解くアルゴリズムも教えてくれるとありがたいです。

2

コードの編集

2017/12/07 13:08

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -140,7 +140,7 @@
140
140
 
141
141
  int value;// このノードが保持している値
142
142
 
143
- int length;
143
+ int length;// 最短路の長さ
144
144
 
145
145
  struct node *left_ptr; // 左枝
146
146
 
@@ -158,21 +158,23 @@
158
158
 
159
159
  int y[100]; //送り火の位置のy座標
160
160
 
161
- int count = 1;
161
+ int count = 1; //データ入力のための変数
162
-
163
-
164
-
162
+
163
+
164
+
165
- void f(int,int*,int*,int*);
165
+ void f(int,int*,int*,int*); //最短路を求める再帰関数
166
-
167
- void print_value(struct node *now);
166
+
168
-
169
- void make_tree(struct node **node,int value,int length);
167
+ void make_tree(struct node **node,int value,int length); //二分木を作る関数
170
168
 
171
169
  int main(){
172
170
 
173
171
 
174
172
 
173
+ //
174
+
175
- //input
175
+ //データの入力
176
+
177
+ //
176
178
 
177
179
  int input[100];
178
180
 
@@ -238,7 +240,17 @@
238
240
 
239
241
  }
240
242
 
241
-
243
+ //
244
+
245
+ //データの入力終了
246
+
247
+ //
248
+
249
+
250
+
251
+
252
+
253
+ //データを出力
242
254
 
243
255
  printf("n = %d,k = %d\n",n,k);
244
256
 
@@ -250,7 +262,9 @@
250
262
 
251
263
 
252
264
 
265
+
266
+
253
- int p = 1;
267
+ int p = 1; //アドレスを確保するための適当な値
254
268
 
255
269
  int q = 2;
256
270
 
@@ -260,10 +274,10 @@
260
274
 
261
275
 
262
276
 
277
+ //答えを出力
278
+
263
279
  printf("(x,y) = (%d %d), answer = %d\n",p,q,r);
264
280
 
265
- print_value(root);
266
-
267
281
 
268
282
 
269
283
  return 0;
@@ -272,13 +286,21 @@
272
286
 
273
287
 
274
288
 
289
+
290
+
291
+ // *l は(x[n],y[n])が見える最短路の長さ
292
+
293
+ // (a[n],b[n])は(x[n],y[n])が見える最短の位置とすると、
294
+
295
+ // (*a,*b) は(a[n],b[n])に対応する。
296
+
275
297
  void f(int n ,int *a,int *b,int *l){
276
298
 
277
299
  if(n != 0){
278
300
 
279
301
  f(n-1,a,b,l);
280
302
 
281
- int pre_a = *a;
303
+ int pre_a = *a; //(a[n-1] , b[n-1]) = (pre_a,pre_b)
282
304
 
283
305
  int pre_b = *b;
284
306
 
@@ -304,7 +326,7 @@
304
326
 
305
327
 
306
328
 
307
- //最短路が同じだった時、分岐
329
+ //(a[n-1],b[n-1])から(x[n],y[n])見える位置、(a[n],b[n)同じだった時、分岐するのだが、ここの実装方法がわかリマセン。
308
330
 
309
331
  *a = x[n];
310
332
 
@@ -346,6 +368,8 @@
346
368
 
347
369
 
348
370
 
371
+ //length は(x[n],y[n])が見える最短路の長さ
372
+
349
373
  void make_tree(struct node **node, int value,int length)
350
374
 
351
375
  {
@@ -394,8 +418,6 @@
394
418
 
395
419
 
396
420
 
397
- // テキストから取り出した数値をノードの数値と比較
398
-
399
421
  // 現在のノードより大きかったら正。小さかったら負。等しかったら0
400
422
 
401
423
  if ((*node)->value < value) {
@@ -442,24 +464,6 @@
442
464
 
443
465
 
444
466
 
445
- void print_value(struct node *now)
446
-
447
- {
448
-
449
- if (now == NULL)
450
-
451
- return;
452
-
453
-
454
-
455
- print_value(now->left_ptr);
456
-
457
- printf("%d %d\n", now->value,now->length);
458
-
459
- print_value(now->right_ptr);
460
-
461
- }
462
-
463
467
 
464
468
 
465
469
  ```

1

コードの追加

2017/12/07 12:57

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -72,7 +72,7 @@
72
72
 
73
73
  池通に向かうかを選ぶことができる.
74
74
 
75
- さて, 送り火を全て見るために歩くのにかかる
75
+ さて, 送り火を全て見るために歩くのに五分かかる
76
76
 
77
77
  最短時間はいくらかであろうか.
78
78
 
@@ -80,15 +80,15 @@
80
80
 
81
81
 
82
82
 
83
- 今, ある自然数k に対して[ k; k] に座標を持つ
83
+ 今, ある自然数k に対して[ k, k] に座標を持つ
84
-
84
+
85
- ような, (2k + 1) (2k + 1) の正方格子の原点
85
+ ような, (2k + 1) × (2k + 1) の正方格子の原点
86
-
86
+
87
- (0; 0) に居るとする. この格子の一区画を歩くの
87
+ (0,0) に居るとする. この格子の一区画を歩くの
88
88
 
89
89
  に1 単位時間かかる. ある順番でn 個の座標ペ
90
90
 
91
- ア(xi; yi), k xi; yi k, i = 1; 2; : : : ; n が
91
+ ア(xi,yi), -k <= xi,yi <= k(i = 1,2,...,n)
92
92
 
93
93
  与えられ, 全ての送り火を与えられた順番で見
94
94
 
@@ -96,6 +96,370 @@
96
96
 
97
97
 
98
98
 
99
+ 入力形式はテキストファイルinput.txtに入っていて、入力形式は
100
+
101
+ n
102
+
103
+ k
104
+
105
+ x1 y1
106
+
107
+ x2 y2
108
+
109
+ ・ ・
110
+
111
+ ・ ・
112
+
113
+ ・ ・
114
+
115
+ xn yn
116
+
117
+
118
+
119
+
120
+
121
+
122
+
99
123
  この問題を再帰法と二分木を使ってC言語でときたいんですが、実装方法がわかりません。
100
124
 
101
125
  できれば動的計画法で解く方法も教えてくれるとありがたいです。
126
+
127
+
128
+
129
+ ちなみに未完成のソースコードはこちらです。fという二分木と絡めた再帰関数の実装方法がよくわかりません。
130
+
131
+ ```C言語
132
+
133
+ #include<stdio.h>
134
+
135
+ #include<stdlib.h>
136
+
137
+
138
+
139
+ struct node {
140
+
141
+ int value;// このノードが保持している値
142
+
143
+ int length;
144
+
145
+ struct node *left_ptr; // 左枝
146
+
147
+ struct node *right_ptr; // 右枝
148
+
149
+ };
150
+
151
+ // ツリーの頂点 root
152
+
153
+ static struct node *root = NULL;
154
+
155
+
156
+
157
+ int x[100]; //送り火の位置のx座標
158
+
159
+ int y[100]; //送り火の位置のy座標
160
+
161
+ int count = 1;
162
+
163
+
164
+
165
+ void f(int,int*,int*,int*);
166
+
167
+ void print_value(struct node *now);
168
+
169
+ void make_tree(struct node **node,int value,int length);
170
+
171
+ int main(){
172
+
173
+
174
+
175
+ //input
176
+
177
+ int input[100];
178
+
179
+ int ret;
180
+
181
+ int a,b;
182
+
183
+
184
+
185
+ FILE *file;
186
+
187
+ file = fopen("input.txt","r");
188
+
189
+ if(file == NULL) {
190
+
191
+ printf("the file can`t be opened\n");
192
+
193
+ return -1;
194
+
195
+ }
196
+
197
+ int m = 0;
198
+
199
+ while(( ret = fscanf( file , "%d %d" , &a , &b )) != EOF ) {
200
+
201
+ input[m] = a;
202
+
203
+ m++;
204
+
205
+ input[m] = b;
206
+
207
+ m++;
208
+
209
+ }
210
+
211
+ fclose(file);
212
+
213
+ // end input
214
+
215
+
216
+
217
+ int n = input[0];// 送り火の数(n)
218
+
219
+ int k = input[1];// (2k+1)x(2k+1)の格子のサイズ
220
+
221
+ int now_x,now_y = 0; //現在の位置
222
+
223
+
224
+
225
+ //送り火の位置の入力
226
+
227
+ for(int v = 2; v < m; v++){
228
+
229
+ if(v % 2 == 0){
230
+
231
+ x[v / 2] = input[v];
232
+
233
+ }else{
234
+
235
+ y[ (v-1)/2 ] = input[v];
236
+
237
+ }
238
+
239
+ }
240
+
241
+
242
+
243
+ printf("n = %d,k = %d\n",n,k);
244
+
245
+ for(int v = 1; v < n+1; v++){
246
+
247
+ printf("(x[%d],y[%d]) = (%d,%d)\n",v,v,x[v],y[v]);
248
+
249
+ }
250
+
251
+
252
+
253
+ int p = 1;
254
+
255
+ int q = 2;
256
+
257
+ int r = 20;
258
+
259
+ f(n,&p,&q,&r);
260
+
261
+
262
+
263
+ printf("(x,y) = (%d %d), answer = %d\n",p,q,r);
264
+
265
+ print_value(root);
266
+
267
+
268
+
269
+ return 0;
270
+
271
+ }
272
+
273
+
274
+
275
+ void f(int n ,int *a,int *b,int *l){
276
+
277
+ if(n != 0){
278
+
279
+ f(n-1,a,b,l);
280
+
281
+ int pre_a = *a;
282
+
283
+ int pre_b = *b;
284
+
285
+ int pre_l = *l;
286
+
287
+ if(abs(x[n] - pre_a) < abs(y[n]- pre_b)){
288
+
289
+ *a = x[n];
290
+
291
+ *b = pre_b;
292
+
293
+ *l = *l + abs(x[n] - pre_a);
294
+
295
+ }else if (abs(x[n] - pre_a) > abs(y[n]- pre_b)){
296
+
297
+ *a = pre_a;
298
+
299
+ *b = y[n];
300
+
301
+ *l = *l + abs(y[n] - pre_b);
302
+
303
+ }else{
304
+
305
+
306
+
307
+ //最短路が同じだった時、分岐
308
+
309
+ *a = x[n];
310
+
311
+ *b = pre_b;
312
+
313
+ *l = *l + abs(x[n] - pre_a);
314
+
315
+ make_tree(root->right_ptr,count,*l);
316
+
317
+ count++;
318
+
319
+
320
+
321
+ *a = pre_a;
322
+
323
+ *b = y[n];
324
+
325
+ *l = *l + abs(y[n] - pre_b);
326
+
327
+ make_tree(root->left_ptr,count,*l);
328
+
329
+ count++;
330
+
331
+ }
332
+
333
+
334
+
335
+ }else{
336
+
337
+ *a = 0;
338
+
339
+ *b = 0;
340
+
341
+ *l = 0;
342
+
343
+ }
344
+
345
+ }
346
+
347
+
348
+
349
+ void make_tree(struct node **node, int value,int length)
350
+
351
+ {
352
+
353
+ int result; // 数値の大小比較結果
354
+
355
+
356
+
357
+ // ノードが存在しない場合
358
+
359
+ if ((*node) == NULL) {
360
+
361
+
362
+
363
+ // 新しい領域を割り当てノードを作成する
364
+
365
+ (*node) = malloc(sizeof(struct node));
366
+
367
+ if ((*node) == NULL){
368
+
369
+ fprintf(stderr, "NULL");
370
+
371
+ exit (8);
372
+
373
+ }
374
+
375
+
376
+
377
+ // メンバを初期化
378
+
379
+ (*node)->left_ptr = NULL;
380
+
381
+ (*node)->right_ptr = NULL;
382
+
383
+ (*node)->value = value;
384
+
385
+ (*node)->length = length;
386
+
387
+
388
+
389
+ // make_tree関数を終了
390
+
391
+ return;
392
+
393
+ }
394
+
395
+
396
+
397
+ // テキストから取り出した数値をノードの数値と比較
398
+
399
+ // 現在のノードより大きかったら正。小さかったら負。等しかったら0
400
+
401
+ if ((*node)->value < value) {
402
+
403
+ result = 1;
404
+
405
+ } else if ((*node)->value > value) {
406
+
407
+ result = -1;
408
+
409
+ } else if ((*node)->value == value) {
410
+
411
+ result = 0;
412
+
413
+ }
414
+
415
+
416
+
417
+ // 現在の数値が既にあれば、新たなノードは作成せずmake_tree関数を終了
418
+
419
+ if (result == 0)
420
+
421
+ return;
422
+
423
+
424
+
425
+ // 大きかったら右枝に移動
426
+
427
+ if (0 < result) {
428
+
429
+ make_tree(&(*node)->right_ptr, value,length);
430
+
431
+ }
432
+
433
+ // 小さかったら左枝に移動
434
+
435
+ else {
436
+
437
+ make_tree(&(*node)->left_ptr, value,length);
438
+
439
+ }
440
+
441
+ }
442
+
443
+
444
+
445
+ void print_value(struct node *now)
446
+
447
+ {
448
+
449
+ if (now == NULL)
450
+
451
+ return;
452
+
453
+
454
+
455
+ print_value(now->left_ptr);
456
+
457
+ printf("%d %d\n", now->value,now->length);
458
+
459
+ print_value(now->right_ptr);
460
+
461
+ }
462
+
463
+
464
+
465
+ ```