初めて自分の家と他人の家が違う、と意識した時

for文を使って2番目に小さい値を出力するようにしたいのですが、どんなプログラムにすればいいでしょうか?
2重ループになりますか?

解る方お願いします。

A 回答 (9件)

2回ループでやるなら、


まず回答4補足にある方法で一番小さい数を求めます。
その時に一番小さい数が存在する配列番号も一緒に覚えておきます。
で、もう一度最初からループしなおして、
今度は一番小さい数が存在する配列番号を除いた
一番小さい数を求めます。
すると、それは2番目に小さい数になります。

でも、1回ループでもできるし、その方が効率的だと思いますよ。
その場合は、回答4補足にある方法のループの中で
一番小さい数を求めるところを少し工夫します。
まず一番小さい数を覚えておく変数first_minと
二番目に小さい数を覚えておく変数second_minを用意します。
調べるデータがfirst_min以下なら、first_minの値を
second_minに移してからfirst_minに今のデータを覚えます。
それ以外でsecond_min以下なら、second_minに今のデータを覚えます。
あと、first_minとsecond_minを初期化するところも少し工夫が
いりますね。

もしかすると配列が1個しかない場合にどうするか
ということも考える必要があるかもしれません。

これをヒントにコーディングしてみてください。
    • good
    • 0
この回答へのお礼

回答ありがとうございました!

お礼日時:2008/11/28 09:59

>for文を使って2番目に小さい値を出力するようにしたいのですが、・・



 プログラムって、汎用性があると便利です。
 「2番目に小さい値」を出したとたん「5番目は?」と、また作り直すのでは・・。

で、質問者様の No.4 さんへの補足ソースをイジッテみました。
  (BorlandC++5.6.4)。

 ・「1番小さい数」を「任意番目の数」としました(外に for 文追加)。
 ・任意番目まで求めるには、直前番目までの順番確定状態をなんらかの形で「保存」しておく必要があります。
 ・ここでは、データ配列の先頭から小さい順に「入れ換える」というかたちで「保存」しました。
 ・入れ換えは、両手に持った2つのコップの内容物の入れ換えを想定すると判り易いかと・・。
 
   他に、空コップ(ここでは min )ひとつが必要ですよね。

 ・全データ個数分入れ換えると、データ配列は、小さい順に並び換わります → 「ソート」。

結果
・習っていない「ソート」の「ひとつの手法」が習得できました。
・質問者様のソースが、中核?であったことがわかったはず(下の k を 0 で固定)。

課題
・「何番目の数」でなく「全体ソート」にするには、・・iTarget 部分は・・?
・下のソースは、内側の for 文で、条件に合った都度、入れ換えているが・・?

#include <stdio.h>

int GetOrderVal( int iCnt, int iTarget, int data[] )
{
 int min = -999, i, k;

 for( k = 0; k < iTarget; k++ ){ // 任意番目まで

  min = data[ k ];

  for( i = ( k + 1 ); i < iCnt; i++ ){

   if( min > data[ i ] ){ // 新たな小さい値

    min = data[ i ]; // 以降、入れ換え作業

    data[ i ] = data[ k ]; // 前のステップで「空」にしたものに代入
    data[ k ] = min; //  〃 結果 [ i ] と [ k ] が入れ換わる
   }
  }
 }
 return( min );
}
void main()
{
 int data[ 50 ] = { 1, 1 ,3, 3, 5, 6 };

 printf( "%d\n", GetOrderVal( 6, 2, data ) ); // 2番目に小さい数
 printf( "%d\n", GetOrderVal( 6, 5, data ) ); // 5番目 〃
}
注:インデントに全角空白を用いています。タブに一括変換して下さい。
    • good
    • 0
この回答へのお礼

回答ありがとうございました!

お礼日時:2008/11/28 09:51

つまり, 「最小値を求める」ためには「現在までの暫定的な最小値」を記憶しておけばいいということですね. では, 「2番目に小さい値」を求めるためにはどうすればいいと思いますか? なお, 「現在までの暫定的に 2番目に小さい値」だけ覚えておいてもダメだということは予め指摘しておきましょう.


理論的には「k番目に小さい値」のみがほしいなら線形時間なんだけど, 実際にはソートした方が速かったりするのは事実>#5.

この回答への補足

「現在までの暫定的な最小値」を記憶している時に、「2番目に小さい値」を記憶したところでやめればいいのですか…?

補足日時:2008/11/05 23:49
    • good
    • 0
この回答へのお礼

回答ありがとうございました!

お礼日時:2008/11/28 10:00

#2です。


ちょっと考えてみたのですが、無理にfor1個でやるよりも、for2個のほうが楽そうです。どうもすみません。

ところで、こういうケースはどうなるのでしょうか?
配列の中身が例えば
1,1,3,3,5,6
だった場合、一番小さな数はもちろん1ですが、2番目に小さい数は1なのでしょうか?それとも3なのでしょうか?

この回答への補足

その場合は1になります。
1番小さい数が2つ以上あったら、2番目に小さい数は1番小さい数となります。

補足日時:2008/11/05 18:38
    • good
    • 0
この回答へのお礼

回答ありがとうございました!

お礼日時:2008/11/28 09:52

No.3です。



 No.3の回答の方法で処理を実現し、入力値全部についてできるように
拡張してからソートを習うと
 “結局、ソートした方が早いじゃん!”
と思うようになります。
    • good
    • 0

「いちばん小さい数の出力方法」でどのようなことをしているのか説明できますか?

この回答への補足

一番小さい数を出力するには
min=data[0];
for(i=1;i<5;i++){
if (min>data[i]){
min=data[i];
}
}
としました。
最初に一つ指定して、残りの数を一つずつ比較していき、小さい方を新しい最小値にする…
といった感じですか?上手く言葉にできなくてすいません。

補足日時:2008/11/05 18:16
    • good
    • 0

 こんにちは。



 今後の事を考えて小さい順に配列に入れる方法がいいかと思います。
そうすると3番目とか4番目に小さい値とかにも対応可能です。

 ご参考までに。
    • good
    • 0
この回答へのお礼

回答ありがとうございました!

お礼日時:2008/11/28 09:51

う~ん、for文は1つで済むと思いますけどね。


一番小さな数の出力方法がわかるのなら、それにちょっと手を加えるだけですよ。

この回答への補足

>一番小さな数の出力方法がわかるのなら
それはわかります。それに何を加えればいいのかわからないんです…。

補足日時:2008/11/05 17:47
    • good
    • 0

ソートしたらどこでも取り出せます


バブルソートなら2重ループになります

この回答への補足

初心者なのでまだ「ソート」というのは習っていません。
ただ2回for文を使うだけらしいのですが…

補足日時:2008/11/05 17:13
    • good
    • 0
この回答へのお礼

回答ありがとうございました!

お礼日時:2008/11/28 09:50

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報