#3
by かずま » 7年前
何が悪かったのか?
どのようにして解決したのかを書いてください。
フォーラムルールに従ってください。
さて、i のループの回数を減らしてみました。
コード:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 10
void print(int a[], int n)
{
for (int i = 0; i < n; i++) printf(" %d", a[i]);
putchar('\n');
}
void sort(int a[], int n)
{
int i, j, k, temp;
for (i = 0; i < n - 1; i = k) {
k = n - 1;
for (j = n - 1; j > i; j--) {
if (a[j-1] > a[j]) {
temp = a[j-1], a[j-1] = a[j], a[j] = temp;
k = j;
}
}
printf("[i=%d, k=%d]", i, k), print(a, n);
}
}
int main(void)
{
int a[N] = { 1, 2, 4, 6, 4, 7, 9, 8, 7, 9 };
int b[N] = { 9, 8, 7, 4, 5, 6, 3, 2, 1, 0 };
print(a, N);
sort(a, N);
print(a, N);
sort(a, N);
print(a, N);
print(b, N);
sort(b, N);
print(b, N);
}
内側のループで最後に交換の起こった場所を憶えておくと、
それ以前はソート済みなので、次回は後ろからそこまでを
スキャンすれば良いことになり、i が 1ずつ増えるのではなく、
一度も交換が行われなかった場合、ソートはすぐに終了します。
実行結果
コード:
1 2 4 6 4 7 9 8 7 9
[i=0, k=4] 1 2 4 4 6 7 7 9 8 9
[i=4, k=8] 1 2 4 4 6 7 7 8 9 9
[i=8, k=9] 1 2 4 4 6 7 7 8 9 9
1 2 4 4 6 7 7 8 9 9
[i=0, k=9] 1 2 4 4 6 7 7 8 9 9
1 2 4 4 6 7 7 8 9 9
9 8 7 4 5 6 3 2 1 0
[i=0, k=1] 0 9 8 7 4 5 6 3 2 1
[i=1, k=2] 0 1 9 8 7 4 5 6 3 2
[i=2, k=3] 0 1 2 9 8 7 4 5 6 3
[i=3, k=4] 0 1 2 3 9 8 7 4 5 6
[i=4, k=5] 0 1 2 3 4 9 8 7 5 6
[i=5, k=6] 0 1 2 3 4 5 9 8 7 6
[i=6, k=7] 0 1 2 3 4 5 6 9 8 7
[i=7, k=8] 0 1 2 3 4 5 6 7 9 8
[i=8, k=9] 0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
後ろからスキャンするので、1回のスキャンで、
一番小さいものは先頭に出ますが、
一番大きいものは 1つシフトされるだけなのが
わかります。
何が悪かったのか?
どのようにして解決したのかを書いてください。
フォーラムルールに従ってください。
さて、i のループの回数を減らしてみました。
[code=c]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 10
void print(int a[], int n)
{
for (int i = 0; i < n; i++) printf(" %d", a[i]);
putchar('\n');
}
void sort(int a[], int n)
{
int i, j, k, temp;
for (i = 0; i < n - 1; i = k) {
k = n - 1;
for (j = n - 1; j > i; j--) {
if (a[j-1] > a[j]) {
temp = a[j-1], a[j-1] = a[j], a[j] = temp;
k = j;
}
}
printf("[i=%d, k=%d]", i, k), print(a, n);
}
}
int main(void)
{
int a[N] = { 1, 2, 4, 6, 4, 7, 9, 8, 7, 9 };
int b[N] = { 9, 8, 7, 4, 5, 6, 3, 2, 1, 0 };
print(a, N);
sort(a, N);
print(a, N);
sort(a, N);
print(a, N);
print(b, N);
sort(b, N);
print(b, N);
}
[/code]
内側のループで最後に交換の起こった場所を憶えておくと、
それ以前はソート済みなので、次回は後ろからそこまでを
スキャンすれば良いことになり、i が 1ずつ増えるのではなく、
一度も交換が行われなかった場合、ソートはすぐに終了します。
実行結果
[code=text]
1 2 4 6 4 7 9 8 7 9
[i=0, k=4] 1 2 4 4 6 7 7 9 8 9
[i=4, k=8] 1 2 4 4 6 7 7 8 9 9
[i=8, k=9] 1 2 4 4 6 7 7 8 9 9
1 2 4 4 6 7 7 8 9 9
[i=0, k=9] 1 2 4 4 6 7 7 8 9 9
1 2 4 4 6 7 7 8 9 9
9 8 7 4 5 6 3 2 1 0
[i=0, k=1] 0 9 8 7 4 5 6 3 2 1
[i=1, k=2] 0 1 9 8 7 4 5 6 3 2
[i=2, k=3] 0 1 2 9 8 7 4 5 6 3
[i=3, k=4] 0 1 2 3 9 8 7 4 5 6
[i=4, k=5] 0 1 2 3 4 9 8 7 5 6
[i=5, k=6] 0 1 2 3 4 5 9 8 7 6
[i=6, k=7] 0 1 2 3 4 5 6 9 8 7
[i=7, k=8] 0 1 2 3 4 5 6 7 9 8
[i=8, k=9] 0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
[/code]
後ろからスキャンするので、1回のスキャンで、
一番小さいものは先頭に出ますが、
一番大きいものは 1つシフトされるだけなのが
わかります。