回答編集履歴

13

補足追加、用語統一

2018/12/26 14:43

投稿

退会済みユーザー
test CHANGED
@@ -18,11 +18,11 @@
18
18
 
19
19
  インデックスiからインデックスlenまでの配列要素にpivot以上の値が集まっています。
20
20
 
21
- **その時(pivot以上の値が格納されている配列の)先頭位置はA+iで、その配列の長さはlen-iなので**
21
+ **その時(pivot以上の値が格納されている配列の)開始位置はA+iで、その配列の長さはlen-iなので**
22
22
 
23
23
  quicksort(A + i, len - i); // *2 という関数の呼び方をしています。
24
24
 
25
- つまり「A[i]からA[len]までの配列にpivot以上の値が格納されている、それをソートしてください」という意味です。
25
+ つまり「A[i]からA[len](A[i+(len-i)])までの配列にpivot以上の値が格納されている、それをソートしてください」という意味です。
26
26
 
27
27
  3.0)~~中央値を選ぶことはできません。中央値を選ぼうとする行為に時間がかかってしまうので。なので少ない計算量で中央値に近い値を選ぶことがポイントです。たとえば二つの値をランダムにとってその平均をpivotにするとか。~~
28
28
 

12

補足追加

2018/12/26 14:43

投稿

退会済みユーザー
test CHANGED
@@ -8,9 +8,9 @@
8
8
 
9
9
  疑問2.0)はい、そうです。
10
10
 
11
- 疑問2.1)第一引数が配列の開始位置です。第二引数には配列の長さを渡しています。
11
+ 疑問2.1)第一引数がその配列の開始位置です。第二引数にはその配列の長さ**(開始位置に長さ足せばその配列の末尾がわかる)**を渡しています。
12
-
12
+
13
- *1を抽象的に言うと「pivot以下の値が集まった配列をクイックソートしてください、その配列の開始位置はAでその配列の要素の数はiです」という意味です。
13
+ *1を抽象的に言うと「pivot以下の値が集まった配列をクイックソートしてください、その配列の開始位置はAでその配列の要素の数はiです」という意味です。つまり「A[0]からA[i]までの配列にpivot以下の値が格納されている、それをソートしてください」という意味です。
14
14
 
15
15
  今、インデックス0からインデックスiまでの配列要素にpivot以下の値が集まっています。
16
16
 
@@ -22,6 +22,8 @@
22
22
 
23
23
  quicksort(A + i, len - i); // *2 という関数の呼び方をしています。
24
24
 
25
+ つまり「A[i]からA[len]までの配列にpivot以上の値が格納されている、それをソートしてください」という意味です。
26
+
25
27
  3.0)~~中央値を選ぶことはできません。中央値を選ぼうとする行為に時間がかかってしまうので。なので少ない計算量で中央値に近い値を選ぶことがポイントです。たとえば二つの値をランダムにとってその平均をpivotにするとか。~~
26
28
 
27
29
  ごめんなさい、質問内容が読めてませんでした。その三つの値から中央値を選ぶことは可能です。

11

表記の統一

2018/12/26 14:38

投稿

退会済みユーザー
test CHANGED
@@ -8,19 +8,19 @@
8
8
 
9
9
  疑問2.0)はい、そうです。
10
10
 
11
- 疑問2.1)第二引数には配列の長さを渡しています。
11
+ 疑問2.1)第一引数が配列の開始位置です。第二引数には配列の長さを渡しています。
12
-
12
+
13
- *1を抽象的に言うと「pivot以下の値が集まった配列をクイックソートしてください、その配列の要素の数はlargeです」という意味です。
13
+ *1を抽象的に言うと「pivot以下の値が集まった配列をクイックソートしてください、その配列の開始位置はAでその配列の要素の数はiです」という意味です。
14
-
14
+
15
- 第一引数が配列の開始位置です。今、インデックス0からインデックスiまでの配列要素にpivot以下の値が集まっています。
15
+ 今、インデックス0からインデックスiまでの配列要素にpivot以下の値が集まっています。
16
16
 
17
17
  ~~インデックスlen-iからインデックスlenまでの配列要素にpivot以上の値が集まっています。~~
18
18
 
19
19
  インデックスiからインデックスlenまでの配列要素にpivot以上の値が集まっています。
20
20
 
21
- **その時(pivot以上の値が格納されている配列の)先頭位置はA+iで、その配列の長さはlen-iなので
21
+ **その時(pivot以上の値が格納されている配列の)先頭位置はA+iで、その配列の長さはlen-iなので**
22
-
22
+
23
- quicksort(A + i, len - i); // *2 という関数の呼び方をしています。**
23
+ quicksort(A + i, len - i); // *2 という関数の呼び方をしています。
24
24
 
25
25
  3.0)~~中央値を選ぶことはできません。中央値を選ぼうとする行為に時間がかかってしまうので。なので少ない計算量で中央値に近い値を選ぶことがポイントです。たとえば二つの値をランダムにとってその平均をpivotにするとか。~~
26
26
 

10

誤記修正

2018/12/26 14:33

投稿

退会済みユーザー
test CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  インデックスiからインデックスlenまでの配列要素にpivot以上の値が集まっています。
20
20
 
21
- **その時開始位置はa+iで、その配列の長さはlen-iなので
21
+ **その時(pivot以上の値が格納されている配列の)先頭位置はA+iで、その配列の長さはlen-iなので
22
22
 
23
23
  quicksort(A + i, len - i); // *2 という関数の呼び方をしています。**
24
24
 

9

疑問2.1の誤記修正

2018/12/26 14:25

投稿

退会済みユーザー
test CHANGED
@@ -14,7 +14,13 @@
14
14
 
15
15
  第一引数が配列の開始位置です。今、インデックス0からインデックスiまでの配列要素にpivot以下の値が集まっています。
16
16
 
17
- インデックスlen-iからインデックスlenまでの配列要素にpivot以上の値が集まっています。
17
+ ~~インデックスlen-iからインデックスlenまでの配列要素にpivot以上の値が集まっています。~~
18
+
19
+ インデックスiからインデックスlenまでの配列要素にpivot以上の値が集まっています。
20
+
21
+ **その時開始位置はa+iで、その配列の長さはlen-iなので
22
+
23
+ quicksort(A + i, len - i); // *2 という関数の呼び方をしています。**
18
24
 
19
25
  3.0)~~中央値を選ぶことはできません。中央値を選ぼうとする行為に時間がかかってしまうので。なので少ない計算量で中央値に近い値を選ぶことがポイントです。たとえば二つの値をランダムにとってその平均をpivotにするとか。~~
20
26
 

8

誤記修正

2018/12/26 14:23

投稿

退会済みユーザー
test CHANGED
@@ -12,9 +12,9 @@
12
12
 
13
13
  *1を抽象的に言うと「pivot以下の値が集まった配列をクイックソートしてください、その配列の要素の数はlargeです」という意味です。
14
14
 
15
- 第一引数が配列の開始位置です。今、AからA+1までの配列要素にpivot以下の値が集まっています。
15
+ 第一引数が配列の開始位置です。今、インデックス0からインデックスiまでの配列要素にpivot以下の値が集まっています。
16
-
16
+
17
- A+iからA+lenまでpivot以上の値が集まっています。
17
+ インデックスlen-iからインデックスlenまでの配列要素にpivot以上の値が集まっています。
18
18
 
19
19
  3.0)~~中央値を選ぶことはできません。中央値を選ぼうとする行為に時間がかかってしまうので。なので少ない計算量で中央値に近い値を選ぶことがポイントです。たとえば二つの値をランダムにとってその平均をpivotにするとか。~~
20
20
 

7

疑問3.0に対する回答修正

2018/12/26 14:15

投稿

退会済みユーザー
test CHANGED
@@ -20,9 +20,31 @@
20
20
 
21
21
  ごめんなさい、質問内容が読めてませんでした。その三つの値から中央値を選ぶことは可能です。
22
22
 
23
- 場合は配列ランダムに三つで、中を返してあげればいいと思います。
23
+ 三つとりたはランダムに選ぶのもいいすし質問者様がいうように先頭、真ん、末尾のでもいいと思います。
24
+
24
-
25
+ 質問者様が実装した関数でpivotを選んでも上手く動作しました。
26
+
25
- 実装としては引数に、1)対象となる配列の先頭要素、2)その配列の長さ 渡して関数内で配列中からランダムに三つ選んで中央値を返す(もしくはその添字)ようにればいいかと思います
27
+ pivot部分以下のように書き換えれば上手く動作すると思います
28
+
29
+
30
+
31
+ ```c
32
+
33
+ int index;
34
+
35
+ index = median3(A,0,len/2,len);
36
+
37
+ int pivot = A[index];
38
+
39
+
40
+
41
+
42
+
43
+ ```
44
+
45
+
46
+
47
+
26
48
 
27
49
 
28
50
 

6

疑問3.0に対する回答を修正

2018/12/26 14:04

投稿

退会済みユーザー
test CHANGED
@@ -16,7 +16,13 @@
16
16
 
17
17
  A+iからA+lenまでpivot以上の値が集まっています。
18
18
 
19
- 3.0)中央値を選ぶことはできません。中央値を選ぼうとする行為に時間がかかってしまうので。なので少ない計算量で中央値に近い値を選ぶことがポイントです。たとえば二つの値をランダムにとってその平均をpivotにするとか。
19
+ 3.0)~~中央値を選ぶことはできません。中央値を選ぼうとする行為に時間がかかってしまうので。なので少ない計算量で中央値に近い値を選ぶことがポイントです。たとえば二つの値をランダムにとってその平均をpivotにするとか。~~
20
+
21
+ ごめんなさい、質問内容が読めてませんでした。その三つの値から中央値を選ぶことは可能です。
22
+
23
+ その場合は配列の中からランダムに三つ選んで、中央値を返してあげればいいと思います。
24
+
25
+ 実装としては引数に、1)対象となる配列の先頭要素、2)その配列の長さ を渡して関数内で配列の中からランダムに三つ選んで中央値を返す(もしくはその添字)ようにすればいいかと思います。
20
26
 
21
27
 
22
28
 

5

用語修正(集合→配列)

2018/12/26 13:43

投稿

退会済みユーザー
test CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  疑問2.1)第二引数には配列の長さを渡しています。
12
12
 
13
- *1を抽象的に言うと「pivot以下の値が集まった集合をクイックソートしてください、その集合の要素の数はlargeです」という意味です。
13
+ *1を抽象的に言うと「pivot以下の値が集まった配列をクイックソートしてください、その配列の要素の数はlargeです」という意味です。
14
14
 
15
15
  第一引数が配列の開始位置です。今、AからA+1までの配列要素にpivot以下の値が集まっています。
16
16
 
@@ -88,7 +88,7 @@
88
88
 
89
89
  printspace(deep);
90
90
 
91
- printf("集合の中身:");
91
+ printf("配列の中身:");
92
92
 
93
93
  for (k = 0; k < len; k++) {
94
94
 
@@ -108,7 +108,7 @@
108
108
 
109
109
  printspace(deep);
110
110
 
111
- printf("集合の要素数が1以下なのでソート終了 要素の値:%d 深さ:%d\n",A[0], deep);
111
+ printf("配列の要素数が1以下なのでソート終了 要素の値:%d 深さ:%d\n",A[0], deep);
112
112
 
113
113
  return;
114
114
 
@@ -148,19 +148,19 @@
148
148
 
149
149
  printspace(deep);
150
150
 
151
- printf("pivot:%d以下の集合leftをクイックソートする\n", pivot);
151
+ printf("pivot:%d以下の配列leftをクイックソートする\n", pivot);
152
152
 
153
153
  quicksort(A, i, deep+1);
154
154
 
155
155
  printspace(deep);
156
156
 
157
- printf("pivot:%d以上の集合rightをクイックソートする\n", pivot);
157
+ printf("pivot:%d以上の配列rightをクイックソートする\n", pivot);
158
158
 
159
159
  quicksort(A + i, len - i, deep+1);
160
160
 
161
161
  printspace(deep);
162
162
 
163
- printf("集合の中身(ソート後):");
163
+ printf("配列の中身(ソート後):");
164
164
 
165
165
  for (k = 0; k < len; k++) {
166
166
 
@@ -196,20 +196,20 @@
196
196
 
197
197
  「-----」このprint出力で再帰の深さを示しています。
198
198
 
199
- pivot:99以上の集合rightをクイックソートする
199
+ pivot:99以上の配列rightをクイックソートする
200
-
200
+
201
- -----集合の中身:782 99 **★これがソート前の配列の中身**
201
+ -----配列の中身:782 99 **★これがソート前の配列の中身**
202
-
202
+
203
- -----pivot:99以下の集合leftをクイックソートする
203
+ -----pivot:99以下の配列leftをクイックソートする
204
-
204
+
205
- ----------集合の中身:99
205
+ ----------配列の中身:99
206
-
206
+
207
- ----------集合の要素数が1以下なのでソート終了 要素の値:99 深さ:2
207
+ ----------配列の要素数が1以下なのでソート終了 要素の値:99 深さ:2
208
-
208
+
209
- -----pivot:99以上の集合rightをクイックソートする
209
+ -----pivot:99以上の配列rightをクイックソートする
210
-
210
+
211
- ----------集合の中身:782
211
+ ----------配列の中身:782
212
-
212
+
213
- ----------集合の要素数が1以下なのでソート終了 要素の値:782 深さ:2
213
+ ----------配列の要素数が1以下なのでソート終了 要素の値:782 深さ:2
214
-
214
+
215
- -----集合の中身(ソート後):99 782 **★これがソート後の配列の中身**
215
+ -----配列の中身(ソート後):99 782 **★これがソート後の配列の中身**

4

見やすさ改善(ソート前とソート後に配列の中身を出力)

2018/12/26 13:31

投稿

退会済みユーザー
test CHANGED
@@ -158,6 +158,22 @@
158
158
 
159
159
  quicksort(A + i, len - i, deep+1);
160
160
 
161
+ printspace(deep);
162
+
163
+ printf("集合の中身(ソート後):");
164
+
165
+ for (k = 0; k < len; k++) {
166
+
167
+ printf("%d ", A[k]);
168
+
169
+ }
170
+
171
+ printf("\n");
172
+
173
+
174
+
175
+
176
+
161
177
  }
162
178
 
163
179
 
@@ -177,3 +193,23 @@
177
193
 
178
194
 
179
195
  ```
196
+
197
+ 「-----」このprint出力で再帰の深さを示しています。
198
+
199
+ pivot:99以上の集合rightをクイックソートする
200
+
201
+ -----集合の中身:782 99 **★これがソート前の配列の中身**
202
+
203
+ -----pivot:99以下の集合leftをクイックソートする
204
+
205
+ ----------集合の中身:99
206
+
207
+ ----------集合の要素数が1以下なのでソート終了 要素の値:99 深さ:2
208
+
209
+ -----pivot:99以上の集合rightをクイックソートする
210
+
211
+ ----------集合の中身:782
212
+
213
+ ----------集合の要素数が1以下なのでソート終了 要素の値:782 深さ:2
214
+
215
+ -----集合の中身(ソート後):99 782 **★これがソート後の配列の中身**

3

コード 出力のみやすさ改善

2018/12/26 13:27

投稿

退会済みユーザー
test CHANGED
@@ -82,11 +82,33 @@
82
82
 
83
83
  void quicksort(int *A, int len, int deep) {
84
84
 
85
+
86
+
87
+ int k;
88
+
89
+ printspace(deep);
90
+
91
+ printf("集合の中身:");
92
+
93
+ for (k = 0; k < len; k++) {
94
+
95
+ printf("%d ", A[k]);
96
+
97
+ }
98
+
99
+ printf("\n");
100
+
101
+
102
+
103
+
104
+
105
+
106
+
85
107
  if (len < 2){
86
108
 
87
109
  printspace(deep);
88
110
 
89
- printf("集合の長さが1以下なのでソート終了 要素の値:%d 深さ:%d\n",A[0], deep);
111
+ printf("集合の要素数が1以下なのでソート終了 要素の値:%d 深さ:%d\n",A[0], deep);
90
112
 
91
113
  return;
92
114
 
@@ -97,18 +119,6 @@
97
119
  int pivot = A[len / 2];
98
120
 
99
121
 
100
-
101
- printspace(deep);
102
-
103
- int k;
104
-
105
- for (k = 0; k < len; k++) {
106
-
107
- printf("%d ", A[k]);
108
-
109
- }
110
-
111
- printf("\n");
112
122
 
113
123
 
114
124
 
@@ -164,4 +174,6 @@
164
174
 
165
175
  }
166
176
 
177
+
178
+
167
179
  ```

2

余計な空白削除

2018/12/26 13:16

投稿

退会済みユーザー
test CHANGED
@@ -138,13 +138,13 @@
138
138
 
139
139
  printspace(deep);
140
140
 
141
- printf("pivot:%d以下の集合leftをクイックソートする\n ", pivot);
141
+ printf("pivot:%d以下の集合leftをクイックソートする\n", pivot);
142
142
 
143
143
  quicksort(A, i, deep+1);
144
144
 
145
145
  printspace(deep);
146
146
 
147
- printf("pivot:%d以上の集合rightをクイックソートする\n ", pivot);
147
+ printf("pivot:%d以上の集合rightをクイックソートする\n", pivot);
148
148
 
149
149
  quicksort(A + i, len - i, deep+1);
150
150
 

1

補足追加

2018/12/26 12:48

投稿

退会済みユーザー
test CHANGED
@@ -1,3 +1,7 @@
1
+ 勘違いして申し訳ございません。
2
+
3
+
4
+
1
5
  疑問1.0)はい、そうです。
2
6
 
3
7
  疑問1.1)はい、そうです。
@@ -13,3 +17,151 @@
13
17
  A+iからA+lenまでpivot以上の値が集まっています。
14
18
 
15
19
  3.0)中央値を選ぶことはできません。中央値を選ぼうとする行為に時間がかかってしまうので。なので少ない計算量で中央値に近い値を選ぶことがポイントです。たとえば二つの値をランダムにとってその平均をpivotにするとか。
20
+
21
+
22
+
23
+ 処理の流れを理解しやすくする為にprint文を仕込んでみました。
24
+
25
+ これを実行してみてください。
26
+
27
+
28
+
29
+ ```c
30
+
31
+ #include <stdio.h>
32
+
33
+
34
+
35
+ void quicksort(int *A, int len, int deep);
36
+
37
+ void printspace(int deep);
38
+
39
+
40
+
41
+ int main (void) {
42
+
43
+ int a[] = {4, 65, 2, -31, 0, 99, 2, 83, 782, 1,3};
44
+
45
+ int n = sizeof a / sizeof a[0];
46
+
47
+ printf("%d\n", n);
48
+
49
+
50
+
51
+ int i;
52
+
53
+ for (i = 0; i < n; i++) {
54
+
55
+ printf("%d ", a[i]);
56
+
57
+ }
58
+
59
+ printf("\n");
60
+
61
+
62
+
63
+ quicksort(a, n, 0);
64
+
65
+
66
+
67
+ for (i = 0; i < n; i++) {
68
+
69
+ printf("%d ", a[i]);
70
+
71
+ }
72
+
73
+ printf("\n");
74
+
75
+
76
+
77
+ return 0;
78
+
79
+ }
80
+
81
+
82
+
83
+ void quicksort(int *A, int len, int deep) {
84
+
85
+ if (len < 2){
86
+
87
+ printspace(deep);
88
+
89
+ printf("集合の長さが1以下なのでソート終了 要素の値:%d 深さ:%d\n",A[0], deep);
90
+
91
+ return;
92
+
93
+ }
94
+
95
+
96
+
97
+ int pivot = A[len / 2];
98
+
99
+
100
+
101
+ printspace(deep);
102
+
103
+ int k;
104
+
105
+ for (k = 0; k < len; k++) {
106
+
107
+ printf("%d ", A[k]);
108
+
109
+ }
110
+
111
+ printf("\n");
112
+
113
+
114
+
115
+ int i, j;
116
+
117
+ for (i = 0, j = len - 1; ; i++, j--) {
118
+
119
+ while (A[i] < pivot) i++;
120
+
121
+ while (A[j] > pivot) j--;
122
+
123
+
124
+
125
+ if (i >= j) break;
126
+
127
+
128
+
129
+ int temp = A[i];
130
+
131
+ A[i] = A[j];
132
+
133
+ A[j] = temp;
134
+
135
+ }
136
+
137
+
138
+
139
+ printspace(deep);
140
+
141
+ printf("pivot:%d以下の集合leftをクイックソートする\n ", pivot);
142
+
143
+ quicksort(A, i, deep+1);
144
+
145
+ printspace(deep);
146
+
147
+ printf("pivot:%d以上の集合rightをクイックソートする\n ", pivot);
148
+
149
+ quicksort(A + i, len - i, deep+1);
150
+
151
+ }
152
+
153
+
154
+
155
+ void printspace(int deep){
156
+
157
+ int i;
158
+
159
+ for(i=0;i<deep;i++){
160
+
161
+ printf("-----");
162
+
163
+ }
164
+
165
+ }
166
+
167
+ ```