• ベストアンサー

ソート

お世話になります。配列のソートなのですが、どうも思い通りの結果になりません。 配列の中から最大値と最小値を探し、最小値を配列0に、最大値を配列の最後に移動します。その2つ以外の数字の順番は変えません。 例) {4,3,2,0,1,2} 最小値は0、最大値は4なので→{0,3,2,1,2,4} {4,3,2,1} → {1,3,2,4} {1,3,2,4,} → {1,3,2,4} 流れとしては、まず最小値を求め配列0に移動させ、次に最大値を求め配列の最後に移動させようと思います。 プログラムは以下のように組みました。 public int[] sortOfSort(int[] array) { int count_min = 0; int min = array[0]; for (int i = 0; i < array.length-1; i++) { // 最小値を求める if (min > array[i + 1]) { min = array[i + 1]; count_min++; // 最小値の配列のインデックスを確保 } } for (int k = count_min; k > 0; k--) { // 最小値の移動 int temp_min = array[k - 1]; array[k - 1] = array[k]; array[k] = temp_min; } int count_max = 0; int max = array[0]; for (int j = 0; j < array.length-1; j++) { // 最大値を求める if (max < array[j + 1]) { max = array[j + 1]; count_max++; // 最大値の配列のインデックスを確保 } } for (int l = count_max; l < array.length-1; l++) { //最大値の移動 int temp_max = array[l + 1]; array[l + 1] = array[l]; array[l] = temp_max; } return array; } 間違っているところがわかりましたら宜しくお願いします。

  • Java
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • isi0611
  • ベストアンサー率34% (46/134)
回答No.3

お疲れ様です。 まずfor文を4回も使ってしまってますね。 私なら性能を考えてまず、最小値・最大値を探すために1回。 そして配列に設定しなおすために1回。 でfor文2回で済ませますね。 参考例としてあげておきます。 public int[] sortOfSort(int[] array) { int min = array[0]; int max = array[0]; int min_index = 0; int max_index = 0; for(int i=0; i<array.length; i++) { if (min > array[i]) { min = array[i]; min_index = i; } if (max < array[i]) { max = array[i]; max_index = i; } } int[] new_array = new int[array.length]; new_array[0] = min; new_array[array.length-1] = max; int count = 1; for(int i=0; i<array.length; i++) { if (min_index != i && max_index != i) { new_array[count] = array[i]; count++; } } return new_array; }

lockwell
質問者

お礼

確かにfor文一回で最小値最大値求めるほうが賢いですね! 新しく配列を定義して入れていったほうがやりやすいです!ありがとうございました!

その他の回答 (2)

  • askaaska
  • ベストアンサー率35% (1455/4149)
回答No.2

どこまでは正しく動いているか は把握しているのかな? 使えるならデバッガ 使えないならSystem.out.printを駆使して まずはどこまで正しく動いているのかを 確認してみよう。 そうすればcount_minとcount_maxの値が 想定しているのと全く違うことに気づくはず。 もうちょっとHINTあげると 最初のforループ for (int i = 0; i < array.length-1; i++) { // 最小値を求める if (min > array[i + 1]) { min = array[i + 1]; count_min++; // 最小値の配列のインデックスを確保 } } 変数iは配列のインデックスだよね。 count_minの値はiとは一緒に増加しないのはわかるかな? 蛇足だけど 最大値と最小値の検索は forループ1回でできるよ。

lockwell
質問者

お礼

>count_minの値はiとは一緒に増加しないのはわかるかな? 確かにその通りですね。if文から出さなければいけませんでした・・・。 動作確認しながらまたやってみます!ありがとうございました!

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.1

思った通りの結果にならないのは「最小値および最大値がどこに入っているかを覚えておく方法が間違っている」のが原因です。

lockwell
質問者

お礼

その通りでした。ありがとうございます!

関連するQ&A

  • java(バブルソート/単純挿入ソート)

    以下のプログラムを「バブルソートもしくは単純挿入ソートのプログラムに変更しなさい」という課題が出ました。 どのようにすればよろしいでしょうか? import java.util.*; public class SelectSort { //プログラムクラス名 //整列プログラム public static void main(String[] args){ //整列用 int 型配列 int[] target; int elems = KeyboardInput.askInt("要素数? "); //配列を乱数で初期化する target = setArray(elems); //初期状態を表示 display(target); //整列メソッドの呼び出し sortArray(target); //整列結果の表示 display(target); } //配列を乱数で初期化するメソッド static int[] setArray(int elems){ // 要素数個の int 型変数の確保 int[] array = new int[elems]; //乱数利用ための宣言 Random generator = new Random(); //乱数の最大値・最小値 int max = 100; int min = 0; //generator.nextDouble() で 0から1までのdouble型乱数発生 for(int i=0 ; i<array.length ; i++) { array[i] = (int)((max-min)*(generator.nextDouble())+min); } return array; } //配列の状態を表示 static void display(int[] array){ for(int i=0 ; i<array.length ; i++) { System.out.print(array[i]+" "); } System.out.println(""); } static void sortArray(int[] array){ //配列のはじめから最後まで繰り返す for( int i = 0; i < array.length-1 ; i++){ int min_id = i; int min = array[i]; //範囲中でもっとも小さい要素を探す for( int j=i+1 ; j< array.length ; j++ ) { if( array[j] < min ){ min = array[j]; min_id = j ; } } //範囲の始めと置き換える int tmp = array[i]; array[i] = array[min_id]; array[min_id] = tmp; //display(array); } } }

  • C言語 最大値と最小値を求めて表示するプログラム

    はじめまして。 C言語を学習中です。 下記の問題演習の解答として記載されているプログラムがどうしても理解できません。 特にプログラムの最後の方のwhile文で最大値と最小値の判定をしているのかと思いますが、どのような計算をして判定しているのでしょうか。 while (array[i] != -1) { if (array[i] > *max) *max = array[i]; if (array[i] < *min) *min = array[i]; i++; 具体的に教えてください。 よろしくお願い致します。 ●問題 0~100の範囲で入力された複数の数値の中から、 最大値と最小値を求めて表示するプログラムを作成せよ。 -1が入力された場合は入力の終わりと判定する。 ただし、最大値と最小値はmain関数以外の一つの関数の中で求める。 また、入力された数値を記憶する配列の要素数は10とし、 それ以上入力された場合はエラーが起きても仕方ないこととする。 ヒント:配列の中に -1 があればデータの終わりだと判断できる。 ヒント:最小値を探すには、最大値を記憶した変数との比較を繰り返せば良い。 ●解答 #include <stdio.h> void maxmin(int array[],int *max,int *min); int main(void) { int i = 0,array[10],max,min; do { printf("%d 番目の数:",i + 1); scanf("%d",&array[i]); i++; } while (array[i - 1] != -1); maxmin(array,&max,&min); printf("最大値 %d : 最小値 %d\n",max,min); return 0; } void maxmin(int array[],int *max,int *min) { int i = 0; *max = 0; *min = 100; while (array[i] != -1) { if (array[i] > *max) *max = array[i]; if (array[i] < *min) *min = array[i]; i++; } }

  • C言語 ソートについて

    #include <stdio.h> #include <stdbool.h> #define NUM_ARRAY 4 #define NUM_DATA 5 int count_swap = 0; // 交換回数 int count_comparison = 0; // 比較回数 void selection_sort(int a[], int n) { } int main(void) { int data[NUM_ARRAY][NUM_DATA] = {{9, 7, 5, 6, 8}, {9, 8, 7, 6, 5}, {5, 6, 7, 8, 9}, {5, 6, 8, 7, 9}}; for (int i = 0; i < NUM_ARRAY; i++) { count_swap = 0; count_comparison = 0; int d[NUM_DATA]; copy_array(data[i], d, NUM_DATA); // 配列のコピー printf("----------------\n"); print_array(d, NUM_DATA); // ソート前の配列の表示 selection_sort(d, NUM_DATA); // 挿入ソートの実行 print_array(d, NUM_DATA); // ソート後の配列の表示 printf("比較回数: %d\n", count_comparison); // 比較回数の表示 printf("交換回数: %d\n", count_swap); // 交換回数の表示 } } 上の雛形を使って選択ソートを実行するという問題なのですが途中までそれっぽいのは出来たのですが上手くいかないので解答をお願いします。 下に自分が今書いているものを置いておきます。 #include <stdbool.h> #include <stdio.h> #define NUM_ARRAY 4 #define NUM_DATA 5 int count_swap = 0; int count_comparison = 0; void swap(int d[], int i, int j) { count_swap += 1; printf("swap a[%d] = %d, a[%d] = %d\n", i, d[i], j, d[j]); int temp = d[i]; d[i] = d[j]; d[j] = temp; } void copy_array(int *a, int *b, int n) { for (int i = 0; i < n; i++) { b[i] = a[i]; } } void print_array(int d[], int n) { for (int i = 0; i < n; i++) { printf("%d ", d[i]); } printf("\n"); } bool compare(int d[], int i, int j) { count_comparison += 1; printf("compare a[%d] = %d, a[%d] = %d\n", i, d[i], j, d[j]); if (d[i] > d[j]) { return true; } else { return false; } } void selection_sort(int d[], int n) { int min; for (int i = 0; i < n - 1; i++) { min = i; for (int j = i + 1; j < i; j++) { if (compare(d, min, j)) { min = j; } } swap(d, i, min); print_array(d, n); } } int main(void) { int data[NUM_ARRAY][NUM_DATA] = { {9, 7, 5, 6, 8}, {9, 8, 7, 6, 5}, {5, 6, 7, 8, 9}, {5, 6, 8, 7, 9}}; for (int i = 0; i < NUM_ARRAY; i++) { count_swap = 0; count_comparison = 0; int d[NUM_DATA]; copy_array(data[i], d, NUM_DATA); // 配列のコピー printf("----------------\n"); print_array(d, NUM_DATA); // ソート前の配列の表⽰ selection_sort(d, NUM_DATA); // 挿⼊ソートの実⾏ print_array(d, NUM_DATA); // ソート後の配列の表⽰ printf("⽐較回数: %d\n", count_comparison); // ⽐較回数の表⽰ printf("交換回数: %d\n", count_swap); // 交換回数の表⽰ } }

  • 配列

    最後にもう一つだけお願いします。ずっと格闘しても解決できません・・ 配列の中の数字で、偶数を全て奇数の前にもって行きます 例) {1,0,1,0,0,1,1} → {0,0,0,1,1,1,1} {3,3,2} → {2,3,3} {2,2,2} → {2,2,2} 流れとしては、まず奇数の数を数えます。これは何回シフトするから知るためです。 配列0から奇数を探し、あればそれを一番最後の配列へとシフトします。 奇数を探す作業が一度終わっても、まだシフトさせないといけない奇数があるかもしれないので(奇数が連続で並んでる場合)、最初に数えた奇数の数分だけちゃんとシフトするようにしようと思います。 public void evensLeft(int[] array) { int odd=0; for (int i = 0; i < array.length; i++) { if(array[i]%2!=0) odd++; //奇数の個数 } while (odd>0) { //奇数分シフトするためのカウント for(int j=0;j<array.length;j++){ //奇数を探す if (array[j] % 2 != 0) { odd--; //奇数のカウントを1減らす for (int k = j; k < array.length-1; k++) { //その奇数を一番最後に移動 int temp = array[k+1]; array[k+1] = array[k]; array[k] = temp; } } } } return array; } いくつかの例では動くのですが、{3,3,2}の例だと配列0に3が来てしまいます。色々変えてみても結果無理でした・・・ どなたかご教授お願いします。

    • ベストアンサー
    • Java
  • 参考書の演習問題

    クラスはMaxAndMinOfInt フィールド int型の配列(名前はnumbersとします)のみ コンストラクタ 引数で与えられたScannerから整数を順次読み取る。最初に読み取った整数を配列サイズとみなして、int型の配列を生成し、numbersで参照する。その後、整数を読み取ってはnumbers[0],numbers[1],・・・へ順に代入していき、配列サイズ分だけ読み取れば終了。 メソッド void showAll() numbers中の全要素を判りやすく表示する int max() numbers中の最大値を返す int min() numbers中の最小値を返す クラスの機能を確認するためのmainメソッド public static void main(String[] args){   Scanner kbScanner = new Scanner(System.in);   MaxAndMinOfInt array = new MaxAndMinOfInt(kbScanner);   array.showAll();   System.out.printf("最小値は%dです. \n", array.min());   System.out.printf("最大値は%dです. \n", array.max()); } 実行例 これは配列サイズ→5 2 4 6 10 1 ←これはキーボード入力 [2, 4, 6, 10, 1] 最小値は1です. 最大値は10です. 以下は自分で打ち込んでみたものです import java.util.Scanner; public class MaxAndMinOfInt { int[] numbers; public MaxAndMinOfInt(Scanner scanner) { numbers = new int[0]; Scanner kbScanner = new Scanner(System.in); System.out.println(""); int numbers = kbScanner.nextInt(); for (int i = 0;i < numbers; i++) { System.out.print((i + 1)); } } public void showAll() { for (int i = 0; i < numbers.length; i++) { System.out.printf("[]", numbers[i]); } } public int max() { int max = 0; max = numbers[0]; for(int i = 1; i < numbers.length; i++){ if(max < numbers[i]) max = numbers[i]; } return max; } public int min() { int min = 0; min = numbers[0]; for(int i = 1; i < numbers.length; i++){ if(min > numbers[i]) min = numbers[i]; } return min; } public static void main(String[] args) { Scanner kbScanner = new Scanner(System.in); MaxAndMinOfInt array = new MaxAndMinOfInt(kbScanner); array.showAll(); System.out.printf("最小値は%dです.\n", array.min()); System.out.printf("最大値は%dです.\n", array.max()); } } これを実行しても実行例のような表示になりません。 どこを変更すればいいか教えてください。

  • 配列のソートと削除

    String型のstrToRemoveで与えられた文字列を配列から探し、あればそれ以降の配列の数字をすべて左にシフトします。 なので配列の大きさは1小さくなります。その結果の配列をreturnで返します。 例) ({"A","B","C","D","B"}, "B")配列1にBがあるのでそれ以降の文字列をすべて左にシフト→ {"A","C","D","B"} ({"A","B","C","D","B"}, "A") 配列0にAがあるのでそれ以降の文字列を左にシフト→ {"B","C","D","B"} プログラムは以下のように組みました。 public class ArrayFun { public String[] oneRemoved(String[] array, String strToRemove) { int count = 0; for (int i = 0; i < array.length; i++) {      if (strToRemove.equals(array[i]) && count == 0) {        for (int j = i; j < array.length - 1; j++) {          array[j] = array[j + 1];        }          count++;      } }      array = new String[array.length - 1];      array[array.length - 1] = null;      return array; } } ちなみにcountは、一度シフトすればもう同じ文字列がそれ以降の配列にあってもシフトはしないので、countでシフトしたかどうかを判断しようと思い付けました。 これでテストメソッドも作るのですが、 import static org.junit.Assert.*; import org.junit.Test; public class ArrayFunTest { @Test public void testoneRemoved() { ArrayFun af = new ArrayFun(); String[] a1 = {"A","B","C","D","B" };//元の配列 String[] a2 = {"A","BB","CCC","DDD","B"};//元の配列 String[] a3 = {"B","C","D","B"};//シフト後の配列 String[] a4 = {"A","BB","CCC","DDD","B"};//シフト後の配列 assertEquals(a3, af.oneRemoved(a1, "A")); assertEquals(a4, af.oneRemoved(a2, "NotHere")); } } 以上のように組むと、assertEqualsの真ん中に黒線が入って自動的に@SuppressWarnings("deprecation")が加えられてしまいます。 実行結果は、({"A","B","C","D","B"}, "A") の例だと、配列0にB が入るはずがnullになっている、とエラーがでます。 どのようにしたら正常に動かせるでしょうか?宜しくお願いします。

    • ベストアンサー
    • Java
  • java初心者です。基本的ですがよろしくおねがいします◎

    下記の内容でコンパイル時にエラーが出てしまいます。 ■問題■要素数10の配列を任意のデータで初期化し、最大値と最小値を求めよ。 import java.io.*; class Ensyu4 {    public static void main(String args[])     {    int i=0,max=0,min=0;//カウンタ、最大値変数、最小値変数         int[10] intArray = {5, 6, 7, 8, 9, 10, 1, 2, 3, 4}; //配列任意初期化         max = intArray[0];         min = intArray[0];         for(i=0;i<10;i++)//最大・最小判定         {             if(max<intArray[i])                 max = intArray[i];             if(min>intArray[i])                 min = intArray[i];         }     System.out.println(max + "が最大値です");     System.out.println(min + "が最小値です");     } } エラーの内容・・・ Ensyu4.java:9: ']' がありません。 int[10] intArray = {5, 6, 7, 8, 9, 10, 1, 2, 3, 4}; //配列任意初 期化 ^ Ensyu4.java:9: 文ではありません。 int[10] intArray = {5, 6, 7, 8, 9, 10, 1, 2, 3, 4}; //配列任意初 期化 ・・・どうやら配列の初期化の仕方が間違っているようなのですが、何が間違っているかわかりません。きっと基本的な間違いなのでしょうが・・・^^; 下記のサイトを参考にさせていただいています◎ http://www.javaroad.jp/java_array1.htm なにとぞご協力お願いいたします^^;

    • ベストアンサー
    • Java
  • ウインドウ終了の取得ができません

    以下にソースを #include <windows.h> #include <stdio.h> static int array[300] = {0}; static int temp[300] = {0}; static int count = 0; static int i = 0; BOOL CALLBACK EnumWindowProc(HWND hwnd, LPARAM lp) { static bool is_first = true; DWORD style = ::GetWindowLong(hwnd, GWL_STYLE); if ( ::IsWindow(hwnd) && ::IsWindowVisible(hwnd) && (style&WS_CAPTION) && !(style&WS_POPUP) ) { char buf[65536]; ::GetWindowText(hwnd, buf, 65535); if ( buf[0] != '\0' ){ if ( is_first ){ is_first = false; } else{ // 配列arrayにハンドルを代入 array[i] = int(hwnd) ; //printf("%d\n",i); i++; // 配列arrayに格納されたハンドル数 count++; } } } return TRUE; } int main(int argc, char** argv) { int a; int j = 0; int k = 0; int t_handend = 0; int flg = 0; char buf[65536]; // 無限ループ while(1){ // 起動しているアプリケーションのハンドル取得(配列arrayに格納) ::EnumWindows(EnumWindowProc, 0); i = 0; // temp内のハンドル数の計算 while(temp[t_handend] != 0){ t_handend++; } for(a=0;a<count;a++){ ::GetWindowText((HWND)array[a], buf, 65535); printf("array[%d]=%d=%s\n",a,array[a],buf); } for(a=0;a<t_handend;a++){ ::GetWindowText((HWND)temp[a], buf, 65535); printf("temp[%d]=%d=%s\n",a,temp[a],buf); } //printf("flg;%d\n",flg); for(k = 0; k < count; k++){ for(j = 0; j < t_handend; j++){ if(array[k] == temp[j]){ flg = 1; break; } } //printf("flg;%d\n",flg); if(flg != 1){ //printf("%d\n", array[i]); //プロセス名取得 ::GetWindowText((HWND)array[k], buf, 65535); printf("%sが起動しました\n", buf); //flg1=1; } flg = 0; } for(k = 0; k < t_handend ; k++){ for(j = 0; j < count; j++){ if(temp[k] == array[j]){ flg = 1; break; } } if(flg != 1){ ::GetWindowText((HWND)temp[k], buf, 65535); if((HWND)temp[k]!=0){ printf("%sが終了しました\n", buf); } //printf("%d\n", temp[i]); } flg = 0; } // tempの更新 for(j = 0; j < count; j++){ temp[j] = array[j]; } for(; j < 300; j++){ temp[j] = 0; } flg = 0; count = 0; puts(""); Sleep(3000); } return 0; } これでウインドが立ち上がったときと終了のログをとろうとしましたが、このままですと終了したウインドの名前がとれません。 どうしたらよいでしょうか。?

  • 最大値と最小値の求め方

    以下はコマンドライン引数で任意の数の整数を受け取って、合計・平均・最大・最小を求めようとしたソースです。 しかし、実行したら最大値と最小値が正しく出ませんでした。 if文が間違っているのかもしれないと思ったのですが、はっきりと『ここが間違っている』という場所が分かりません。 どうかご指摘お願いします。 class Choco { public static void main (String[] args) { int i; int sum = 0; int max; int min; for ( i=0; i<args.length; i++) sum += Integer.parseInt(args[i]); double ave = sum/args.length; max = args.length; min = args.length; if (args.length>max){ max = args.length; } if (args.length<min){ min = args.length; } System.out.println("合計は" + sum + "です。"); System.out.println("平均は" + ave + "です。"); System.out.println("最大値は" + max + "です。"); System.out.println("最小値は" + min + "です。"); } }

    • ベストアンサー
    • Java
  • マージソート内の再帰処理にすいて

    #include<stdio.h> #define MAX 4 int temp[MAX]; void marge(int num[],int left,int right) { int i,j,mid,k   if(left>=right)return; mid=(left+right)/2; marge(num,left,mid);//(1) maege(num,mid+1,right);//(2) for(i=left;i<=mid;i++) temp[i]=num[i]; for(i=mid+1,j=right;i<=right;i++,j--) temp[i]=num]j]; i=left; j=right; for(k=left;k<=right;k++) if(temp[i]<=temp[j]) num[k]=temp[i++]; else num[k]=temp[j--] } マージソート内はこういった関数を記述してエラーもでないのですが、(1)と(2)の処理がよくわかりません。 (1)は再帰的に処理していってif(left>=right)return;の条件を満たした場合に(2)の処理に入っていきますよね? その場合、(2)の処理を行う際に(1)が(2)の再帰より前に記述されているので(1)がまた処理されるのでしょうか? 一連の流れを(1)、(2)を使って表してほしいです。

専門家に質問してみよう