ようこそ ゲスト さん、新規登録(無料)して気になる疑問を解決しませんか?

質問

QNo.3988172 バブルソートについて質問です。
質問者:noname#58788 キーボード入力で10個好きな数字を入れてもらい入力した数字を小さい順に並び替えさらに入力した数を合計して小さい順の入力値と合計値を表示させ0は表示させないというプログラムを作りたいのですが途中から意味が分からなくなってしまいました。
ここを直したらいいなどのアドバイスをお願いします。

#include <stdio.h>

void swap (int *,int *);
void printdata(int *);

main()
{
int a[10];
int n=10;
int i,j;
for(i=0;i<=9;i++)
scanf("%d\n",a[i]);

int kekka;
kekka=a+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8]+a[9];
return kekka;

printdata(a);

for(j=n-1;j>=0;j--){
for(i=0;i<j;i++){
if(a[i]>a[i+1]){
swap(a+i,a+i+1);
printf("[%d]と[%d]を入れ替え\n",i,i+1);
printdata(a);
}
}
}
}

void swap(int *y,int *z)
{
int t;
t= *y;
*y=*z;
*z=t;
}

void printdata(int *a)
{
int i;
for(i=0;i<=9;i++)
printf("%4d",a[i]);
printf("\n");
}
困り度:
  • すぐに回答を!
質問投稿日時:
08/04/30 20:35
この質問に対する回答は締め切られました。
最新から表示回答順に表示

回答

ANo.8 No.3 No.5 No.6の回答者です。

No.7 のご指摘、

>if( i>0 ) i-1;

とんでもない記述ミスですね。

正解は、書いた方が良いかな〜〜
宿題にしておきますか。

がんばってください!! >トビ主(質問者様)
回答者:tig33
種類:アドバイス
どんな人:専門家
自信:自信あり
回答日時:
08/05/02 15:23
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

ANo.7 No.4 です。

( No.6 さんの回答に関連して、「回答」への裏側を・・)

★「バブル」にしなかった理由

 ・ソース(レベル)を見て、それには「早い」と思ったからです。
  (そうは書けない。といって今書いてるけど・・残念)
 ・とはいえ、「質問」どおりに「回答」も判らない訳ではありません。

★「キーボード入力で」・・を省略した理由。

 scanf( "%d\n", &a[i] ); と書くようでは、
 
 質問主旨に行き着くのは、・・と考え省略しました。
 (気づきにくいミスですよね、実行しても・・)
 でも、これ位は自力で・・。

☆ところで、

 質問者様は、No.3 さんへの補足の中程にある、
 
 if( i>0 ) i-1;

 は、何をする命令か、理解されて書かれたのでしょうか。
 (私の環境では、無視されるコードです)
回答者:yama5140
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:
08/05/02 12:41
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

ANo.6 蛇足ながら、A4さんのソートは逐次比較方式と行って、バブルソートではありません。

書籍によっては、私の記述した方法ではなく、隣り合わせを比較して、入れ替えが行われなくなったら、終了というソートを、バブルソートとしていることもあるようです。

(例)
int i,doswap;
do {
 doswap=0;
 for(i=0; i<n-1; i++) {
  if(a[i]>a[i+1]) {
   my_swap(&a[i],&a[i+1]);
   doswap=1;
  }
 }
} while(doswap);


  
  
回答者:tig33
種類:アドバイス
どんな人:専門家
自信:自信あり
回答日時:
08/05/02 11:10
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

ANo.5 まず命題を整理すると、

(1)キーボード入力で10個好きな数字を入れてもらい
(2)入力した数字を小さい順に並び替え
(3)さらに入力した数を合計して
(4)小さい順の入力値と合計値を表示させ0は表示させない


で、プログラムを添削しました。
インデントは全角空白を使用しています。

#include <stdio.h>

//↓記述方法は合っていますが、10個の数ということを引数にする必要があります。
void printdata(int *,int );


void PrintAllData(int *val, int cnt, int sum)
{
 int ct;
 
 //小さい順番に表示(0は表示しない)
 for(ct=0; ct<cnt; ct++) {
  if(*val != 0 ) {
   printf("%4d\n", *val);
  }
  val++;
 }
 
 //合計の表示
 printf("合計 = %d\n", sum);
}

//数値の入れ替え
void my_swap(int *a, int *b)
{
 int w;
 
 w = *a;
 *a = *b;
 *b = w;
}

//メインプログラム(関数)
main()
{
 int a[10];
 int n=10;
 int t;
 int i,j;
 int kekka=0;
 
 //(1)キーボード入力で10個好きな数字を入れてもらい
 //入力すると同時に、合計を計算する
 for(i=0;i<n;i++){
  printf("%d番目の数字を入力して下さい。\n",i+1);
  scanf("%d\n",&a[i]);
  kekka += a[i]; //←合計を計算します
 }
 
 //printdata(a,kekka); //←これは命題には無いので不要

 //小さい順に並べ替え
 for(i=0;i<n-1;i++){
  for(j=0;j<n-1-i;j++){
   if( a[i] > a[i+1] ) {
    my_swap( &a[i], &a[i+1] );
    for(j=i; j>1; j--) {
     if(a[j] < a[j-1]) {
      my_swap(&a[j],&a[j-1]);
     } else {
      break;
     }
    }
    if( i>0 ) i-1;
   }
  }
 }
 
 //全データの表示
 PrintAllData(a, n, kekka);
}


//↓ここから以下は意味不明・・・?
// t=a[j];
// a[j]=a[j+1];
// a[j+1]=t;
//
// printf("[%d]と[%d]を入れ替え\n",i,i+1);



// printdata(a,kekka);


// }
// }
// }

// }

//void printdata(int a,int kekka)  //←プロトタイプ宣言と違っています
void printdata(int *a,int kekka)
{
 int i;
 int n;  //←初期化されていません n=10;が必要

 for(i=0;i<n;i++){
  if(a[i]!=0){
   printf("%4d",a[i]);
  }
 }
 printf("合計 = %d\n",kekka);
}
回答者:tig33
種類:回答
どんな人:専門家
自信:自信あり
回答日時:
08/05/02 10:58
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

ANo.4 >どこを直したらいいか教えて下さい。

 ・kekka は、int の宣言時に初期化されて以後、
   左辺にありませんが・・。
 ・void printdata(int *,int); とのプロトタイプと
   関数本体が異なりますが・・。
 ・お判りとは思いますが、ソート部分はメチャクチャです。
---------------------------------------
ソート(入れ替え)については、
★身の回りのものに置き換えて考えると・・。

 ・2個のコップがあって、
   1つにビール、
   もう1つに日本酒 が入っている。
   
   これらを入れ替えたいとき、
   
 空の一時待避用の『容器1つ』が必要ですよね。
 
   その容器に一旦、ビールを入れて、
   空いたコップに、日本酒を入れる。
   空いたコップに、待避したビールを入れる(◆)。
---------------------------------------
>途中から意味が分からなくなってしまいました。

 あれも、これもですと・・・。

「データ入力」と「0は表示させない」は、件名とは、
 直接関係しませんよね。「ソート」が理解された後で、
 付加されれば、と思います。
(「合計値を表示」は、冒頭の kekka 云々から付加)

★サンプルソースでアドバイスします。

・参考にして頂けましたら、幸いです。

#include <stdio.h>

#define CNT 10

void PrintData( int iVal[] )
{
 int i, iTotal = 0;

 for( i = 0; i < CNT; i++ ){

  iTotal += iVal[i];

  printf( "%4d", iVal[i] );
 }
 printf( " 合計 = %d\n", iTotal );
}
void SortData( int iVal[] )
{
 int i, j, iDum;

 for( i = 0; i < CNT; i++ ){

  for( j = i; j < CNT; j++ ){

   if( iVal[i] < iVal[j] ) continue;

   iDum = iVal[i]; iVal[i] = iVal[j]; iVal[j] = iDum; //(◆)
  }
 }
}
void main()
{
 int iVal[10] = { 991, 2, 3, 454, 155, 236, 557, 98, 9, 60 };

 PrintData( iVal );

 SortData( iVal );

 PrintData( iVal );
}
注:インデントに全角空白を用いています。
  タブに一括変換してお試し下さい。
回答者:yama5140
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:
08/05/02 09:30
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

ANo.3 バブルソートと書いてあったので、ソートしているところを拝見しましたが、これではソート結果が正しく出力されないと思います。
バブルソートの意味を良く理解してください。
与えられたテーブルの各要素を縦に並べて小さい順に並べ替えるとき、上から順に2個を比べて、小さい物が見つかると、入れ替え作業が起きます。
そのとき、入れ替えた要素が更に上と比べて小さいとまた入れ替えが起きる。
この繰り返しが、泡が昇っていくようになるので、バブルソートと言うのだったと思います。

で、

ANo.1さんの指摘を反映して、プログラムしてみました。

for(i=0; i<(n-1); i++) {
 if( a[i] > a[i+1] ) {
  my_swap( &a[i], &a[i+1] );
  for(j=i; j>1; j--) {
   if(a[j] < a[j-1]) {
    my_swap(&a[j],&a[j-1]);
   } else {
    break;
   }
  }
  if( i>0 ) i-1;
 }
}

いかがでしょうか?
回答者:tig33
種類:回答
どんな人:専門家
自信:自信あり
回答日時:
08/05/01 12:35
この回答への補足回答ありがとうございます。
参考にしてやってみたのですが、うまくできません。
どこを直したらいいか教えて下さい。
#include <stdio.h>

void printdata(int *,int);

main()
{
int a[10];
int n=10;
int t;
int i,j;
int kekka=0;
for(i=0;i<n;i++){
printf("%d番目の数字を入力して下さい。\n",i+1);

scanf("%d\n",&a[i]);

}
printdata(a,kekka);

for(i=0;i<n-1;i++){
for(j=0;j<n-1-i;j++){

if( a[i] > a[i+1] ) {
my_swap( &a[i], &a[i+1] );
for(j=i; j>1; j--) {
if(a[j] < a[j-1]) {
my_swap(&a[j],&a[j-1]);
} else {
break;
}
}
if( i>0 ) i-1;
}
}

t=a[j];
a[j]=a[j+1];
a[j+1]=t;

printf("[%d]と[%d]を入れ替え\n",i,i+1);
printdata(a,kekka);


}
}
}

}

void printdata(int a,int kekka)
{
int i;
int n;
for(i=0;i<n;i++){
if(a[i]!=0){
printf("%4d",a[i]);
}
}
printf("合計 = %d\n",kekka);
}
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

ANo.2 > scanf("%d\n",a[i]);
scanf()のマニュアルを見直そう。第二引数。これじゃ数値が入らない。

> kekka=a+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8]+a[9];
> return kekka;
これは何?デバッグ用の処理?
あと、たぶん[0]が抜けてる。しかもここでプログラムが終わっちゃう。

> swap(a+i,a+i+1);
間違っちゃいないが、ここは swap(&a[i],&a[i+1]);とする。その方が意味が通りやすい。

> printf("[%d]と[%d]を入れ替え\n",i,i+1);
printf("[%2d:%4d]と[%2d:%4d]を入れ替え\n",i,a[i],i+1,a[i+1]);
とすれば入れ替えている様子が値を含めて見える。
回答者:tokichim
種類:補足要求
どんな人:経験者
自信:参考意見
回答日時:
08/04/30 23:19
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

ANo.1 これを動作させると どう思った通りになってくれないのかを記述してくれないと答えてあげられないよ。
(判らないからじゃなくて そういう約束になっている)
回答者:SAYKA
種類:補足要求
どんな人:一般人
自信:参考意見
回答日時:
08/04/30 21:57
この回答への補足キーボード入力した数値をバブルソートできれいに並べることができません。
この回答へのお礼この回答にお礼をつける(質問者のみ)
最新から表示回答順に表示