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

回答編集履歴

3

ソートを止め, put/get で検索

2020/04/27 09:33

投稿

jimbe
jimbe

スコア13350

answer CHANGED
@@ -5,9 +5,8 @@
5
5
  テストを簡単にするため, smatrix_read を改造しています.
6
6
 
7
7
  #修正
8
- リストを使うようにし, 2次元動作するようにしました.
8
+ リストを使うようにし, 2次元的に動作するようにしました.
9
9
  データが無い所を 0 表示するようにしました.
10
- ソート部分がテキトウかもしれません.
11
10
  ```c
12
11
  #include <stdio.h>
13
12
  #include <stdlib.h>
@@ -37,58 +36,38 @@
37
36
  SLOBJ *last;
38
37
  } SLIST;
39
38
 
40
- //リスト初期化
39
+ //初期化
41
40
  void slist_init(SLIST *slist) {
42
41
  slist->next = NULL;
43
42
  slist->last = (SLOBJ *)slist;
44
43
  }
45
44
 
46
- //リストに追加
45
+ //書き換えor追加
47
- void slist_append(SLIST *slist, int x, int y, double v) {
46
+ void slist_put(SLIST *slist, int x, int y, double v) {
48
47
  SLOBJ *p;
49
48
 
49
+ for(p=slist->next; p!=NULL; p=p->next) {
50
+ if(p->x == x && p->y == y) {
51
+ p->v = v;
52
+ return;
53
+ }
54
+ }
50
55
  p = slobj_new(x, y, v);
51
56
  slist->last->next = p;
52
57
  slist->last = p;
53
58
  }
54
59
 
55
- //リストをカウント
60
+ //取り出し
56
- int slist_count(SLIST *slist) {
61
+ double slist_get(SLIST *slist, int x, int y) {
57
- int count;
58
62
  SLOBJ *p;
59
63
 
60
- count = 0;
61
- for(p=slist->next; p!=NULL; p=p->next) count++;
64
+ for(p=slist->next; p!=NULL; p=p->next) {
65
+ if(p->x == x && p->y == y) return p->v;
66
+ }
62
- return count;
67
+ return 0.0;
63
68
  }
64
69
 
65
- //リストをソート
66
- void slist_sort(SLIST *slist) {
67
- SLOBJ *o, *p, *q, *t;
68
- int count, changed;
69
-
70
- count = slist_count(slist);
71
- if(count <= 1) return;
72
-
73
- t = NULL;
74
- do { //バブル
75
- changed = 0; //フラグクリア
76
- o = (SLOBJ *)slist;
77
- p = o->next;
78
- q = p->next;
79
- while(q != t) {
80
- if(p->y > q->y || (p->y == q->y && p->x > q->x)) { //p>q
81
- p->next = q->next; q->next = p; o->next = q; //入れ替え
82
- changed = 1; //フラグセット
83
- }
84
- o = o->next; p = o->next; q = p->next; //次
85
- if(q == NULL) slist->last = p;
86
- }
87
- t = p;
88
- } while(changed);
89
- }
90
-
91
- //リストを解放
70
+ //解放
92
71
  void slist_clear(SLIST *slist) {
93
72
  SLOBJ *p, *q;
94
73
  for(p=slist->next; p!=NULL; p=q) {
@@ -129,7 +108,7 @@
129
108
  x = test[k++]; //scanf("%d",&s->a[i].j);
130
109
  y = test[k++];
131
110
  v = test[k++]; //scanf("%lf",&s->a[i].v);
132
- slist_append(&s->a, x, y, v);
111
+ slist_put(&s->a, x, y, v);
133
112
  }
134
113
  return s;
135
114
  }
@@ -141,30 +120,19 @@
141
120
 
142
121
  t = smatrix_new(s->m, s->n);
143
122
  for(p=s->a.next; p!=NULL; p=p->next) {
144
- slist_append(&t->a, p->y, p->x, p->v); //行列変換
123
+ slist_put(&t->a, p->y, p->x, p->v); //行列変換
145
124
  }
146
125
  return t;
147
126
  }
148
127
 
149
128
  //疎行列をプリント
150
129
  void smatrix_print(char *label, SMATRIX *s) {
151
- double v;
152
- SLOBJ *p;
153
-
154
130
  if(label != NULL) printf("%s\n", label);
155
131
  printf("%d %d\n", s->n, s->m);
156
132
 
157
- slist_sort(&s->a);
158
- p = s->a.next;
159
133
  for(int y=1; y<=s->n; y++) {
160
134
  for(int x=1; x<=s->m; x++) {
161
- if(p != NULL && p->x == x && p->y == y) {
162
- v = p->v;
163
- p = p->next;
164
- } else {
165
- v = 0.0;
166
- }
167
- printf("(%d,%d)=%lf%s", x, y, v, x==s->m?"\n":" ");
135
+ printf("(%d,%d)=%lf%s", x, y, slist_get(&s->a,x,y), x==s->m?"\n":" ");
168
136
  }
169
137
  }
170
138
  }

2

コード見直し

2020/04/27 09:33

投稿

jimbe
jimbe

スコア13350

answer CHANGED
@@ -3,20 +3,105 @@
3
3
  ということで, マトリクス生成時に大きさが決まっているのでリストにする必要が無いようですし, 実体とポインタが混在して分かり難く感じましたので, リスト関係を消し, SMATRIX の malloc をするようにしてみました.
4
4
  大きな行列で無ければこのほうが解放抜けはし難いと思います.
5
5
  テストを簡単にするため, smatrix_read を改造しています.
6
+
7
+ #修正
8
+ リストを使うようにし, 2次元で動作するようにしました.
9
+ データが無い所を 0 表示するようにしました.
10
+ ソート部分がテキトウかもしれません.
6
11
  ```c
7
12
  #include <stdio.h>
8
13
  #include <stdlib.h>
9
14
 
10
15
  //要素の構造体
11
16
  typedef struct slobj {
17
+ struct slobj *next; //必ず構造体の先頭にすること
12
- int j;
18
+ int x, y;
13
19
  double v;
14
20
  } SLOBJ;
15
21
 
22
+ //新しい要素を作成
23
+ SLOBJ *slobj_new(int x, int y, double v){
24
+ SLOBJ *p;
25
+
26
+ p = (SLOBJ *)malloc(sizeof(SLOBJ));
27
+ p->next = NULL;
28
+ p->x = x;
29
+ p->y = y;
30
+ p->v = v;
31
+ return p;
32
+ }
33
+
34
+ //リストの構造体
35
+ typedef struct slist {
36
+ SLOBJ *next; //必ず構造体の先頭にすること
37
+ SLOBJ *last;
38
+ } SLIST;
39
+
40
+ //リスト初期化
41
+ void slist_init(SLIST *slist) {
42
+ slist->next = NULL;
43
+ slist->last = (SLOBJ *)slist;
44
+ }
45
+
46
+ //リストに追加
47
+ void slist_append(SLIST *slist, int x, int y, double v) {
48
+ SLOBJ *p;
49
+
50
+ p = slobj_new(x, y, v);
51
+ slist->last->next = p;
52
+ slist->last = p;
53
+ }
54
+
55
+ //リストをカウント
56
+ int slist_count(SLIST *slist) {
57
+ int count;
58
+ SLOBJ *p;
59
+
60
+ count = 0;
61
+ for(p=slist->next; p!=NULL; p=p->next) count++;
62
+ return count;
63
+ }
64
+
65
+ //リストをソート
66
+ void slist_sort(SLIST *slist) {
67
+ SLOBJ *o, *p, *q, *t;
68
+ int count, changed;
69
+
70
+ count = slist_count(slist);
71
+ if(count <= 1) return;
72
+
73
+ t = NULL;
74
+ do { //バブル
75
+ changed = 0; //フラグクリア
76
+ o = (SLOBJ *)slist;
77
+ p = o->next;
78
+ q = p->next;
79
+ while(q != t) {
80
+ if(p->y > q->y || (p->y == q->y && p->x > q->x)) { //p>q
81
+ p->next = q->next; q->next = p; o->next = q; //入れ替え
82
+ changed = 1; //フラグセット
83
+ }
84
+ o = o->next; p = o->next; q = p->next; //次
85
+ if(q == NULL) slist->last = p;
86
+ }
87
+ t = p;
88
+ } while(changed);
89
+ }
90
+
91
+ //リストを解放
92
+ void slist_clear(SLIST *slist) {
93
+ SLOBJ *p, *q;
94
+ for(p=slist->next; p!=NULL; p=q) {
95
+ q = p->next;
96
+ free(p);
97
+ }
98
+ slist_init(slist);
99
+ }
100
+
16
101
  //疎行列の構造体
17
102
  typedef struct {
18
103
  int n, m;
19
- SLOBJ *a;
104
+ SLIST a;
20
105
  } SMATRIX;
21
106
 
22
107
  //新しい疎行列を作成
@@ -26,55 +111,66 @@
26
111
  s = (SMATRIX *)malloc(sizeof(SMATRIX));
27
112
  s->n = n;
28
113
  s->m = m;
29
- s->a = (SLOBJ *)malloc(sizeof(SLOBJ) * n*m);
114
+ slist_init(&s->a);
30
115
  return s;
31
116
  }
32
117
 
33
118
  //標準出力から行列を読み込み、別のメモリに記憶しておく
34
119
  SMATRIX *smatrix_read() {
35
- int i, n, m, k=0;
120
+ int i, n, m, x, y, k=0;
121
+ double v;
36
122
  SMATRIX *s;
37
- int test[] = { 2,3, 1,1, 2,2, 3,3, 1,4, 2,5, 3,6 }; //テストデータ
123
+ int test[] = { 2,3, 1,1,1, /*2,1,2*/ 1,2,4, 2,2,5, 3,2,6, 3,1,3, }; //テストデータ
38
124
 
39
125
  n = test[k++]; //scanf("%d",&n);
40
126
  m = test[k++]; //scanf("%d",&m);
41
127
  s = smatrix_new(n, m);
42
- for (i=0; i<n*m; i++) {
128
+ for (i=0; i<(sizeof(test)/sizeof(int)-2)/3; i++) {
43
- s->a[i].j = test[k++]; //scanf("%d",&s->a[i].j);
129
+ x = test[k++]; //scanf("%d",&s->a[i].j);
130
+ y = test[k++];
44
- s->a[i].v = test[k++]; //scanf("%lf",&s->a[i].v);
131
+ v = test[k++]; //scanf("%lf",&s->a[i].v);
132
+ slist_append(&s->a, x, y, v);
45
133
  }
46
134
  return s;
47
135
  }
48
136
 
49
137
  //疎行列の転置を作成・出力
50
138
  SMATRIX *smatrix_transpose(SMATRIX *s) {
51
- int i;
52
139
  SLOBJ *p;
53
140
  SMATRIX *t;
54
141
 
55
142
  t = smatrix_new(s->m, s->n);
56
- for (i=0; i<s->n*s->m; i++) {
143
+ for(p=s->a.next; p!=NULL; p=p->next) {
57
- p = &t->a[(i%s->m) * t->m + (i/s->m)];
144
+ slist_append(&t->a, p->y, p->x, p->v); //行列変換
58
- p->j = i/s->m + 1;
59
- p->v = s->a[i].v;
60
145
  }
61
146
  return t;
62
147
  }
63
148
 
64
149
  //疎行列をプリント
65
150
  void smatrix_print(char *label, SMATRIX *s) {
66
- int i;
151
+ double v;
152
+ SLOBJ *p;
67
153
 
68
154
  if(label != NULL) printf("%s\n", label);
69
155
  printf("%d %d\n", s->n, s->m);
156
+
157
+ slist_sort(&s->a);
158
+ p = s->a.next;
159
+ for(int y=1; y<=s->n; y++) {
70
- for(i=0; i<s->n*s->m; i++) {
160
+ for(int x=1; x<=s->m; x++) {
71
- printf("%d %lf%s", s->a[i].j, s->a[i].v,
161
+ if(p != NULL && p->x == x && p->y == y) {
162
+ v = p->v;
163
+ p = p->next;
164
+ } else {
165
+ v = 0.0;
166
+ }
72
- i%s->m==s->m-1?"\n":" ");
167
+ printf("(%d,%d)=%lf%s", x, y, v, x==s->m?"\n":" ");
168
+ }
73
169
  }
74
170
  }
75
171
 
76
172
  void smatrix_free(SMATRIX *s) {
77
- free(s->a);
173
+ slist_clear(&s->a);
78
174
  free(s);
79
175
  }
80
176
 
@@ -90,4 +186,15 @@
90
186
  smatrix_free(b);
91
187
  return 0;
92
188
  }
189
+ ```
190
+ ```plain text
191
+ A:
192
+ 2 3
193
+ (1,1)=1.000000 (2,1)=0.000000 (3,1)=3.000000
194
+ (1,2)=4.000000 (2,2)=5.000000 (3,2)=6.000000
195
+ B:
196
+ 3 2
197
+ (1,1)=1.000000 (2,1)=4.000000
198
+ (1,2)=0.000000 (2,2)=5.000000
199
+ (1,3)=3.000000 (2,3)=6.000000
93
200
  ```

1

説明変更

2020/04/27 09:17

投稿

jimbe
jimbe

スコア13350

answer CHANGED
@@ -1,10 +1,8 @@
1
1
  > 根本的に
2
2
 
3
3
  ということで, マトリクス生成時に大きさが決まっているのでリストにする必要が無いようですし, 実体とポインタが混在して分かり難く感じましたので, リスト関係を消し, SMATRIX の malloc をするようにしてみました.
4
- これ解放抜けはし難いと思います.
4
+ 大き行列で無ければこのほうが解放抜けはし難いと思います.
5
5
  テストを簡単にするため, smatrix_read を改造しています.
6
-
7
- ...SLOBJ.j は"列番号"として表示しているだけのようですが構造体内に要るのでしょうか.
8
6
  ```c
9
7
  #include <stdio.h>
10
8
  #include <stdlib.h>