質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

2回答

1924閲覧

配列を昇順、降順に並び替えて表示したいです。

talabagani

総合スコア50

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2021/07/14 12:29

前提・実現したいこと

配列を昇順、降順に並び替えて表示をする。
(Java API のArraysやCollectionsは使いません。)
arraysSortは二つの引数を持つメソッドです。一つは配列。二つ目はboolean。二つ目の引数がtrueなら昇順、falseなら降順です。
displayは配列を表示するメソッド。
changeは配列の中身を入れ替えるメソッド。

arraysSortのなかでchangeは使われる。

発生している問題・エラーメッセージ

順番に並び変わっていません。

エラーメッセージ

該当のソースコード

java

1public class Main5_7 {//1 2 3 public static void main(String[] args){//2 4 int[] arrays1= {96,45,31,29,84,77}; 5 display(arrays1, false); 6 arraySort(arrays1, true); 7 display(arrays1, true); 8 arraySort(arrays1, false); 9 display(arrays1, true); 10 } 11 public static void arraySort(int[] array, boolean orderType) { 12 //3 13 boolean a = true; 14 if(orderType) {//4 15 while(a) { 16 for(int i=0 ; i<array.length-1 ; i++) { 17 a=false; 18 if(array[i]>array[i+1]) { 19 a=true; 20 change(array, i, i+1); 21// int temp= array[i]; 22// array[i]=array[i+1]; 23// array[i+1]=temp; 24 } 25 } 26 } 27 28 } else { 29 while(a) { 30 for(int i=0 ; i<array.length-1 ; i++) { 31 a=false; 32 if(array[i]<array[i+1]) { 33 a=true; 34 change(array, i, i+1); 35 } 36 } 37 } 38 }//4 39 }//3 40 public static void display(int[] array, boolean isSorted) { 41 if(isSorted) { 42 System.out.println("配列は整えられています。"); 43 } else { 44 System.out.println("配列は整えられていません。"); 45 } 46 for(int value : array) { 47 System.out.println(value); 48 }//3 49 } 50 public static void change(int[] array,int i, int j) { 51 int temp; 52 temp = array[i]; 53 array[i] = array[j]; 54 array[j]= temp; 55 } 56 57 58} 59

bash

1配列は整えられていません。 296 345 431 529 684 777 8配列は整えられています。 931 1029 1145 1277 1384 1496 15配列は整えられています。 1645 1777 1884 1996 2031 2129

補足情報(FW/ツールのバージョンなど)

Java version 16.0.1
Eclipse
Mac OS Big Surの環境です。
java -version
java version "16.0.1" 2021-04-20
Java(TM) SE Runtime Environment (build 16.0.1+9-24)
Java HotSpot(TM) 64-Bit Server VM (build 16.0.1+9-24, mixed mode, sharing)
MacBook:09_MinutesToYearsandDayCalculator $

パソコン MacBook(Retina, 12-inch,2017), memory 8GB

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2021/07/14 12:30

課題全部聞いてるのか。
K_3578

2021/07/28 01:10

qiitaで質問してても別に良いんですけどこの質問は解決したんですかね
guest

回答2

0

boolean a = true; とありますが、
a が何のためにあるのかを考えてみてください。

紙に「array: 96 45 31 29 84 77」と書いて、コードを順に追っていくと、
array の値と変数 a と i の値がどう変化するのかを全部書いてみてください。

追記
質問の仕方が間違っています。
何が分からないのかを全く書いていません。
発生している問題が「順番に並び変わっていません。」で、
あとはコードがあるだけです。

a = false; を for文の前に置いてください」と回答しようかと思ったんですが、
そうすると、意味も考えず、「解決しました。ありがとうございます」というコメントが
返ってきて終了することが多いので今回はそのような回答をしませんでした。

a = false;while (a) { のすぐ後に置いたら正しい結果が出るのに、

for(int i=0 ; i<array.length-1 ; i++) { のすぐ後に置いたら
正しい結果が出ないのはなぜですか?

という疑問なら、質問にそう書くべきなんです。

そうすると、次のような回答を書きます。

質問のコードでは、a = false; が for文の中にあります。
配列の要素ごとに、逆順が見つかったかどうかが a に入ります。
for文が終了した時、a に入ったのは、最後の比較の結果だけです。
それ以前の比較の結果は全部無視されます。

やりたいことは、配列を順番に見ていって、一度でも逆順を見つけたら
まだソートが完了していない可能性があるということを a に記録することです。

だから、for文の前に a = false; を置いて、逆順はまだ見つかっていない
という状態にしておいて、for文の中で、一度でも逆順が見つかったら、
a = true; で「逆順があった」とするんです。

追記2
質問のコードで、昇順と降順でほぼ同じコードが 2つ書かれているのが気になります。
Integer.compare を使えば、次のように 1つにできます。

Java

1 public static void arraySort(int[] array, boolean orderType) { 2 int diff = orderType ? 1 : -1; // 比較結果 3 boolean rev; // 逆順検出フラグ 4 do { 5 rev = false; // 逆順無しと仮定 6 for (int i = 1 ; i < array.length; i++) { 7 if (Integer.compare(array[i-1], array[i]) == diff) { 8 rev = true; // 逆順検出 9 change(array, i-1, i); 10 } 11 } 12 } while (rev); // 逆順有りならループ 13 }

投稿2021/07/14 14:06

編集2021/07/15 11:03
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

talabagani

2021/07/15 06:57

whileのすぐ後に while(a) { a=false; と入れたらいいのはわかっているのですが、 なぜ、今の場所ではダメなんだろうって考えてしまっています。
guest

0

前回の『学習方法について』的なやつに書いた気がしますが、

デバッグぐらいしましょう!!!

プログラミングは『書いて終わり』ではありません。

デバッグやテストも含みます。

デバッガを使うなり、いわゆる『printfデバッグ』をするなりしましょう。


デバッグをしたとかなら、その旨を書きましょう。
『どのように試した』とか『その結果』とか。

Javaとかの言語はmainメソッドから始まります。

まずはmainメソッドを探しましょう。

そうすると、Main5_7.mainメソッドになりますね。

この中を読む。

Java

1 // 配列を宣言し、設定 2     int[] arrays1= {96,45,31,29,84,77}; 3 // 表示! (as 降順) 4 display(arrays1, false); 5 // ソート (as 昇順) 6 arraySort(arrays1, true); 7 // 表示! (as 昇順) 8 display(arrays1, true); 9 // ソート (as 降順) 10 arraySort(arrays1, false); 11 // 表示! (as 昇順) 12 display(arrays1, true);

ですね。

displayメソッドとかが呼ばれているので、displayメソッドの中も潜っちゃいましょう!

Java

1 public static void display(int[] array, boolean isSorted) { 2 // 引数 isSorted が trueなら 3 if(isSorted) { 4 // 整えられている扱い 5 System.out.println("配列は整えられています。"); 6 // それ以外(false) なら 7 } else { 8 // 整えられていない扱い 9 System.out.println("配列は整えられていません。"); 10 } 11    // 一つずつ表示 12 for(int value : array) { 13 System.out.println(value); 14 }//3 15 }

これをint[] arrays1= {96,45,31,29,84,77}; の場合でやってみる。

そうすると、想定通りになるはずです。

次に arraySortメソッドが呼ばれています。

なのでこれも潜っちゃいましょう!

Java

1 public static void arraySort(int[] array, boolean orderType) { 2 // boolean型の変数aを宣言(???) 3 boolean a = true; 4 // 引数 orderTypeがtrueなら 5 if(orderType) {//4 6 // フラグ a が trueの間 7 while(a) { 8         // 要素数分ループ 9 for(int i=0 ; i<array.length-1 ; i++) { 10 // 一旦フラグを折る 11 a=false; 12 // ソート済みじゃないなら 13 if(array[i]>array[i+1]) { 14 // フラグを立てて 15 a=true; 16 // 交換!!! 17 change(array, i, i+1); 18// int temp= array[i]; 19// array[i]=array[i+1]; 20// array[i+1]=temp; 21 } 22 } 23 } 24 // それ以外( false )なら 25 } else { 26 // フラグ a が trueの間 27 while(a) { 28 // 要素数分 29 for(int i=0 ; i<array.length-1 ; i++) { 30 // フラグを折る 31           a=false; 32 // ソート済みじゃないなら 33 if(array[i]<array[i+1]) { 34 // フラグを立てて 35 a=true; 36 // 交換!!! 37 change(array, i, i+1); 38 } 39 } 40 } 41 }//4 42 }//3

これを日本語でも英語でも韓国語でも中国語でもスペイン語でもなんでもいいので、自分が読み書きできる言語で書き下してみる。(as 疑似コード)

1. boolean型のフラグ aを用意 2. 引数 orderTypeがtrueなら 2.1. フラグ a が trueの間 2.1.1. 要素数分ループ 2.1.1.1. 一旦フラグ aを折る 2.1.1.2. ソート済みじゃないなら 2.1.1.2.1. フラグ a を立てて 2.1.1.2.2. 交換!!! 3. それ以外(orderType ~ false) なら 3.1. フラグ a が trueの間 3.1.1. 要素数分ループ 3.1.1.1. 一旦フラグ aを折る 3.1.1.2. ソート済みじゃないなら 3.1.1.2.1. フラグ a を立てて 3.1.1.2.2. 交換!!!

これを現実世界で、シミュレーションしてみましょう。
脳内でもいいですが。

そうすると、『んー、なんか(2.1)や(3.1)とかでのフラグa を立てたり折ったりとかの処理、本当に必要か?』と感じませんか?

別にフラグ操作をしなくても、ソートはできます。

それにフラグの役割がほとんどないです。
他のプログラムでフラグを立てたりするのは、『条件分岐』のためです。

今回は、『ソート済みなら、これ以上意味ないからフラグをfalseにして終了する』とかみたいな感じの役割じゃないと意味ない気がします。
無駄な処理。

過去質問(『学習方法』のやつだったかな)でも書いたように、『プログラミングは置いといて、現実世界でならどうするかを考える』的なものをやるべきです。

手作業でやるときに、フラグ管理に相当する処理、しますか?

それに、処理内容も、(2.1)以降と(3.1) 以降、ほとんど同じですよね。
単に 『昇順にする』か『降順にする』かですね。

違いはたった一行。

if( /* ソート済みなら */ )

だけです。
番号だと、(2.1.1.2) と (3.1.1.2)だけです。

同じ処理で、微妙に違うだけの処理のために、コピペのような感じで分岐させるよりも、

たとえば、

Java

1boolean isSorted( int a, int b, boolean oderType );

のような感じでメソッドとして切り出して、

Java

1if( isSorted( array1[i], array1[i-1], false ) ){ 2 // 交換アルゴリズム!! 3}

とかみたいにやった方がいいですよ。

引数の並びはなんでもいいですが、上記の場合は第三引数を『昇順 or 降順』の意味でやるとか。

ただ、可読性を考えた場合、boolean orderType でやるより、
列挙型 ( Enum ) でやった方がいいかも。

仕様として『boolean型の引数を持つこと』的な感じで定められているのなら仕方なくbooleanでやるべきですが。

そして、changeメソッドが呼ばれていますから、これも内部に潜る。

Java

1 public static void change(int[] array,int i, int j) { 2 int temp; 3 temp = array[i]; 4 array[i] = array[j]; 5 array[j]= temp; 6 }

…とやっていく。


後、『値渡し』と『参照渡し』を意識しましょう。
(もしかしたらこれが原因の可能性も?)

投稿2021/07/14 12:54

編集2021/07/15 07:56
BeatStar

総合スコア4962

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

talabagani

2021/07/15 07:04 編集

もちろん、書き出しています。 それでも疑問に思うのです。 whileのすぐ後に while(a) { a=false; といれたらいいことは承知しているんですよ。 それでも、なぜ、今の場所ではだめなんだろうという疑問です。 決して、怠けてデバグをしていないわけではありません。 どんなふうに数字が動くかを考えてもそれでもわからないので、今回このように質問をさせていただきました。 何卒、お気に召さない場合は私のような小物は放っておいて スルーをしていただけないでしょうか?
BeatStar

2021/07/15 07:05

> 決して、怠けてデバグをしていないわけではありません。 デバグではなくて『デバッグ』ですね。まあいいけど。(←よくない) それならそう書くべきでは? 以前の回答にも書きましたが、『回答者は質問者と同じ環境にある…わけじゃないので、提示された情報からしか読み取れない』です。 単に『デバッグしました』ではなくて、 『こういう風にデバッグしました』と実例を出す。 単にコードとかを出すと、『可能性が沢山ある』ので、虱潰しに調べていかないといけないです。 もしかしたら質問者さんがやったことがその中に含まれるかもしれない。 そうなると質問者にとっても回答者にとっても不毛です。 時間の無駄です。 それよりは『こういうことを試しました。ですが結果は……』のように試したこととその結果をそれぞれ書く。 そうすれば、『んー、この可能性はないなぁ……じゃあ、この可能性はどうだろう』と大体絞り込めます。 ※ 別に怒っていません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問