クイックソートについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
はじめ

クイックソートについて

#1

投稿記事 by はじめ » 14年前

このような正解例があるのですが、
[[[  正解例  ]]]
出力結果:
1行目:Input a number: Input a number: Input a number: Input a number: Input a number: Input a number: Input a number: Input a number: Input a number: Input a number: before: 792 530 324 587 202 691 721 734 54 792
2行目:(0, 9) pivot: 0, center: 8
3行目: 54 530 324 587 202 691 721 734 792 792
4行目:(0, 7) pivot: 3, center: 4
5行目: 54 530 324 202 587 691 721 734 792 792
6行目:(0, 3) pivot: 3, center: 1
7行目: 54 530 324 202 587 691 721 734 792 792
8行目:(1, 3) pivot: 2, center: 2
9行目: 54 202 324 530 587 691 721 734 792 792
10行目:(2, 3) pivot: 3, center: 3
11行目: 54 202 324 530 587 691 721 734 792 792
12行目:(4, 7) pivot: 5, center: 5
13行目: 54 202 324 530 587 691 721 734 792 792
14行目:(5, 7) pivot: 6, center: 6
15行目: 54 202 324 530 587 691 721 734 792 792
16行目:(6, 7) pivot: 7, center: 7
17行目: 54 202 324 530 587 691 721 734 792 792
18行目:(8, 9) pivot: 9, center: 9
19行目: 54 202 324 530 587 691 721 734 792 792
20行目:after: 54 202 324 530 587 691 721 734 792 792

自分の出力結果は以下のようになり、18行目だけ違ってしまいます。

1行目:Input a number: Input a number: Input a number: Input a number: Input a number: Input a number: Input a number: Input a number: Input a number: Input a number: before: 792 530 324 587 202 691 721 734 54 792
2行目:(0, 9) pivot: 0, center: 8
3行目: 54 530 324 587 202 691 721 734 792 792
4行目:(0, 7) pivot: 3, center: 4
5行目: 54 530 324 202 587 691 721 734 792 792
6行目:(0, 3) pivot: 3, center: 1
7行目: 54 530 324 202 587 691 721 734 792 792
8行目:(1, 3) pivot: 2, center: 2
9行目: 54 202 324 530 587 691 721 734 792 792
10行目:(2, 3) pivot: 3, center: 3
11行目: 54 202 324 530 587 691 721 734 792 792
12行目:(4, 7) pivot: 5, center: 5
13行目: 54 202 324 530 587 691 721 734 792 792
14行目:(5, 7) pivot: 6, center: 6
15行目: 54 202 324 530 587 691 721 734 792 792
16行目:(6, 7) pivot: 7, center: 7
17行目: 54 202 324 530 587 691 721 734 792 792
18行目:(8, 9) pivot: 8, center: 9
19行目: 54 202 324 530 587 691 721 734 792 792
20行目:after: 54 202 324 530 587 691 721 734 792 792

前に
10行目:(2, 3) pivot: 3, center: 3 が  10行目:(2, 3) pivot: 2, center: 3
16行目:(6, 7) pivot: 7, center: 7 が  16行目:(6, 7) pivot: 6, center: 7
18行目:(8, 9) pivot: 9, center: 9 が  18行目:(8, 9) pivot: 8, center: 9

となっていたので、
else if(right - left <= 1)
return(right);
という条件を付けました。
すると10行目、16行目は改善されたのですが
18行目は、改善されません。
以下のプログラムなのですが、どこを修正していけばいいかわからず、困っています。
どなたか教えていただけないでしょうか?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
void quick(int *, int, int);
#define N 10
int main(void){
int a[N] = {0};
int k = 0;
for (k = 0; k < N ; k++) {
printf("Input a number: ");
scanf("%d", &a[k]);
}
printf("before: ");
for (k = 0; k < N; k++) {
printf("%4d", a[k]);
}
printf("\n");
quick(a, 0, N - 1);

printf("after: ");
for (k = 0; k < N; k++) {
printf("%4d", a[k]);
}
printf("\n");
}
void check(int a[], int left, int right, int p, int center) {
int i = 0;
printf("(%d, %d) pivot: %d, center: %d\n", left, right, p, center);
for (i = 0; i < N; i++) {
printf("%4d", a);
}
printf("\n");
}
int pivot(int a[], int left, int right) {
//
int x = (left + right) / 2;
int a1 = a[left];
int a2 = a[x];
int a3 = a[right];
if((a1==a2) && (a2==a3))
return(left);
else if(right - left <= 1)
return(right);
else if(a1==a2)
return(left);
else if(a1==a3)
return(right);
else if(a2==a3)
return(x);
else if((a1<a2) && (a2<a3))
return(x);

else if((a1<a3) && (a3<a2))
return(right);

else if((a2<a1) && (a1<a3))
return(left);

else if((a2<a3) && (a3<a1))
return(right);


else if((a3<a1) && (a1<a2))
return(left);

else if((a3<a2) && (a2<a1))
return(x);
}
int swap(int *x, int *y) {
int t = *x;
*x = *y;
*y = t;
}
int partition(int a[], int left, int right, int p) {
//
int i,j;
i = left;
j = right;

while(1){

while(a < p){
i++;
}
if(i >= right)
break;
while(p <= a[j]){
j--;
if(j==left){
if(i==left){
i++;
}
break;
}
}
if(j <= left) {
break;
}
if(i>=j){
break;
}
swap(&a, &a[j]);
i = left;
j = right;
}
return(i);
}
void quick(int a[], int left, int right) {
int p = 0; // 軸
int center = 0; // 配列を分ける位置
//
p = pivot(a, left, right);
center = partition(a, left, right, a[p]);
if(right-left<=0)

return;
check(a, left, right, p, center);
quick(a, left, center - 1);
quick(a, center, right);
}
//

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: クイックソートについて

#2

投稿記事 by softya(ソフト屋) » 14年前

codeタグを利用頂く様にお願いします。 http://dixq.net/board/board.html#k10
それと再現テストのために入力データも正確に記入して下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

はじめ

Re: クイックソートについて

#3

投稿記事 by はじめ » 14年前

すいません。見落としてました。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
void quick(int *, int, int);
#define N 10
int main(void){
int a[N] = {0};
int k = 0;
for (k = 0; k < N ; k++) {
printf("Input a number: ");
scanf("%d", &a[k]);
}
printf("before: ");
for (k = 0; k < N; k++) {
printf("%4d", a[k]);
}
printf("\n");
quick(a, 0, N - 1);

printf("after: ");
for (k = 0; k < N; k++) {
printf("%4d", a[k]);
}
printf("\n");
}
void check(int a[], int left, int right, int p, int center) {
int i = 0;
printf("(%d, %d) pivot: %d, center: %d\n", left, right, p, center);
for (i = 0; i < N; i++) {
printf("%4d", a[i]);
}
printf("\n");
}
int pivot(int a[], int left, int right) {
// 
int x = (left + right) / 2;
int a1 = a[left];
int a2 = a[x];
int a3 = a[right];
if((a1==a2) && (a2==a3))
return(left);
else if(right - left <= 1)
return(right);
else if(a1==a2)
return(left);
else if(a1==a3)
return(right);
else if(a2==a3)
return(x);
else if((a1<a2) && (a2<a3))
return(x);

else if((a1<a3) && (a3<a2))
return(right);

else if((a2<a1) && (a1<a3))
return(left); 

else if((a2<a3) && (a3<a1))
return(right);


else if((a3<a1) && (a1<a2))
return(left);

else if((a3<a2) && (a2<a1))
return(x);
}
int swap(int *x, int *y) {
int t = *x;
*x = *y;
*y = t;
}
int partition(int a[], int left, int right, int p) {
// 
int i,j;
i = left;
j = right;

while(1){

while(a[i] < p){
i++;
}
if(i >= right)
break;
while(p <= a[j]){
j--;
if(j==left){
if(i==left){
i++;
}
break;
}
}
if(j <= left) { 
break;
} 
if(i>=j){
break;
}
swap(&a[i], &a[j]);
i = left;
j = right;
}
return(i);
}
void quick(int a[], int left, int right) {
int p = 0; // 軸
int center = 0; // 配列を分ける位置
// 
p = pivot(a, left, right);
center = partition(a, left, right, a[p]);
if(right-left<=0)

return;
check(a, left, right, p, center);
quick(a, left, center - 1);
quick(a, center, right);
}

はじめ

Re: クイックソートについて

#4

投稿記事 by はじめ » 14年前

入力データです。
792
530
324
587
202
691
721
734
54
792

box
記事: 2002
登録日時: 15年前

Re: クイックソートについて

#5

投稿記事 by box » 14年前

はじめ さんが書きました: 自分の出力結果は以下のようになり、18行目だけ違ってしまいます。
正解例と食い違っていること自体に、本当に問題があるのでしょうか。
別に違っていてもいいのではないでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

はじめ

Re: クイックソートについて

#6

投稿記事 by はじめ » 14年前

大学の課題なのですが、採点が自動で、正解例に一致しないといけないとのことなので、これではダメなようです。

前述のとおり、
10行目:(2, 3) pivot: 3, center: 3 が  10行目:(2, 3) pivot: 2, center: 3
16行目:(6, 7) pivot: 7, center: 7 が  16行目:(6, 7) pivot: 6, center: 7
18行目:(8, 9) pivot: 9, center: 9 が  18行目:(8, 9) pivot: 8, center: 9

となっていたところ
rightとleftの位置が隣り合っているという条件で
else if(right - left <= 1)
return(right);
こう場合分けたしたつもりなのですが、
なぜ10行目、16行目は改善され、
18行目は、改善されないままなのでしょうか?

box
記事: 2002
登録日時: 15年前

Re: クイックソートについて

#7

投稿記事 by box » 14年前

そもそも、pivot()の実装って、今ほどややこしくしなくてもいいような気がします。
そこまでいろいろと判断しなくてはならないものなんでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

のり

Re: クイックソートについて

#8

投稿記事 by のり » 14年前

ものすごーくみずらいプログラムです。
インデントをちゃんとしてから貼ってほしかった。

単純にpivot=(left + right )/2;
となってるので最後は(9+9)/2=8
なので最後にpivot=8,center=9となる。

というかleft=9となった時点で終わりでしょ?
それ以上続けるからこうなる。

後プログラムにはコメントを振ってほしい。
いちいち変数がどういう働きをしてるかを確かめるのに時間がかかる。

最後にどうでもいいことだが、int mainで始まっているので、
return で終わるべきではないでしょうか?
もう一個なんでpivotとcenterをわけてるのだろうか?
普通は一緒だと思うんだけどな。オーダーのこと考えているのかな?
このやり方だと必ずo(nlogn)になるのかな?

のり

Re: クイックソートについて

#9

投稿記事 by のり » 14年前

言い忘れた。
入力、出力がきまってるのならなんでscanfでキーボード入力
しているのでしょうか?あらかじめ配列に格納してはだめなの
でしょうか?

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: クイックソートについて

#10

投稿記事 by beatle » 14年前

のり さんが書きました:最後にどうでもいいことだが、int mainで始まっているので、
return で終わるべきではないでしょうか?
C99しか読んでませんが,規格としてはreturnに出会わずにmainの最後の}まで到達した場合,0を返すそうです.

閉鎖

“C言語何でも質問掲示板” へ戻る