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

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

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

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

Q&A

解決済

4回答

3329閲覧

ArrayListを使ったクイックソートのプログラムが作りたい

nikaho

総合スコア3

Java

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

0グッド

0クリップ

投稿2020/06/26 07:07

編集2020/06/26 13:08

前提・実現したいこと

お世話になります。

ArrayListに格納した数値をクイックソートで昇順にソートしたいです。
List内の一番左の数値をピボットとして数値を比較し、それを再起的に繰り返す事でソートしようとしたのですがエラーが出てしまいます。

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

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0 at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64) at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70) at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248) at java.base/java.util.Objects.checkIndex(Objects.java:373) at java.base/java.util.ArrayList.get(ArrayList.java:426) at Quick.Quick(Quick.java:24) at Quick.Quick(Quick.java:35)

該当のソースコード

java

1public class QuickSort { 2 3 ArrayList<Integer> array = new ArrayList<Integer>(); 4 5 //クイックソート 6 void Quick(ArrayList<Integer> array) { 7 int size = array.size(); 8 9 //listの大きさが1なら再帰終了 10 if (size == 1) return; 11 12 ArrayList<Integer> L = new ArrayList<>(), R = new ArrayList<>(); 13 14 //一番左の値をピボットとして分割処理 15 int P = array.get(0); 16 for (int i=1; i<size; i++) { 17 if (P > array.get(i)) { 18 L.add(array.get(i)); 19 }else { 20 R.add(array.get(i)); 21 } 22 } 23 24 //再帰 25 Quick(L); 26 Quick(R); 27 28 array.clear(); 29 30 //分割した値を統合 31 for (int i=0; i<L.size(); i++) { 32 array.add(L.get(i)); 33 } 34 35 array.add(P); 36 37 for (int i=0; i<R.size(); i++) { 38 array.add(R.get(i)); 39 } 40 } 41}

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

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

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

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

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

LouiS0616

2020/06/26 07:10

『Quick』と『Quick1』が混在しているように見えますが、これは意図的ですか?
ozwk

2020/06/26 07:11

array1 は何者でしょうか? 宣言もなしにいきなりコード上に現れます。
nikaho

2020/06/26 07:15

すみません。こちらのミスです。
退会済みユーザー

退会済みユーザー

2020/06/26 12:59

クラス名と同じ名前のメソッド名は・・・・
nikaho

2020/06/26 13:17

質問用に実際の名前と変更して書いています。困惑させてしまい申し訳ないです。修正しました。
LouiS0616

2020/06/26 13:20 編集

質問用に変数名を変更する意図が分かりません。
nikaho

2020/06/26 13:32

クラス名に私的な名称が入っていたのでその部分を省きました。
LouiS0616

2020/06/26 13:50 編集

なるほど。確かにそれならば変更した方が良いでしょうね。 質問を投稿する際は、投稿するコードが元のコードと同じように振る舞うかどうか確認しておくとスムーズかも思います。
nikaho

2020/06/26 14:00

元のコードと同じような振る舞いをするのは重要ですね。以後投稿の際に気をつけます。
guest

回答4

0

ベストアンサー

再帰呼び出しする際はピボットを除去して下さい。
Lの要素が [ピボット, ピボット以下の数値, ...] になると同じパラメータで無限再帰します。

具体的には、次の手順を踏んで下さい。
0. L及びRには、ピボット以外の要素を加えるようにします。(0番目を飛ばせば良い)
0. LとRを統合する際に、ピボットも忘れずくっつけてやります。


なお『分割した値を統合』している部分についてはもっと簡単に書けます。

Java

1// Lの全要素をarrayに追加 2for(...) { array.add(...); } // List#forEachでも良い。 3// ピボットを追加 4array.add(P); 5// Rの全要素をarrayに追加 6...

List#addAllを利用しても良いでしょう。

投稿2020/06/26 07:25

編集2020/06/26 07:29
LouiS0616

総合スコア35668

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

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

nikaho

2020/06/26 13:27

ピボットの除去は盲点でした!教えて下さりありがとうございます。 しかし、コードの方を修正したのですがまだエラーが出てしまうようで...
LouiS0616

2020/06/26 13:35 編集

分割した結果、長さ0のリストをソートしようとする場合があります。 ピボットの取得に失敗しArrayIndexOutOfBoundsException(範囲外アクセス)を引き起こしますね。 再帰の基底条件を見直す必要があります。
LouiS0616

2020/06/26 13:40 編集

なおLに値を追加する条件は P > array.get(i) ではなく P >= array.get(i) のままが良いです。 ここを > で比較してしまうとソートに失敗するケースがあります。どのような場合かはちょっと考えてみて下さい。 [追記] ...と思ったんですけど、どちらでも大丈夫でした。失礼しました。 同じ値が複数含まれるリストのソートに失敗する(同じ値が無視される)と思ったのですが、よく考えるとL.appendに取りこぼされる分がR.appendに移るだけなので問題無いですね。
anndonut

2020/06/26 15:25

自分もArrayListでクイックソート書きました。staticメソッドですね。最初の要素をpivotするのであれば、ArrayListのIteratorを作ってpivotにnext()を食わせてからwhileで回せばスマートなのかと。あとはaddとaddAllが後ろにしか要素を追加できないのでleft, pivot, rightの順でかませてやればソート完了ですね。
guest

0

diff

1- if (size == 1) return; 2+ if (size <= 1) return;

投稿2020/06/27 03:25

kazuma-s

総合スコア8224

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

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

0

6年前に書いた突っ込みどころ満載のソース

java

1import java.util.ArrayList; 2import java.util.List; 3 4public class QuickSort { 5 6 public static <T extends Comparable<T>> List<T> sort(List<T> list) { 7 List<T> retList = new ArrayList<>(list); 8 return sort(retList, 0, retList.size() - 1); 9 } 10 11 public static <T extends Comparable<T>> List<T> sort(List<T> list, int left, int right) { 12 13 if (left < right) { 14 int i = left; 15 int j = right; 16 T pivot = med3(list.get(i), list.get(i + (j - i) / 2), list.get(j)); 17 while (true) { 18 while (list.get(i).compareTo(pivot) < 0) 19 i++; 20 while (pivot.compareTo(list.get(j)) < 0) 21 j--; 22 if (i >= j) 23 break; 24 T a = list.get(i); 25 T b = list.get(j); 26 27 list.set(i, b); 28 list.set(j, a); 29 30 i++; 31 j--; 32 } 33 sort(list, left, i - 1); 34 sort(list, j + 1, right); 35 } 36 37 return list; 38 } 39 40 private static <T extends Comparable<T>> T med3(T x, T y, T z) { 41 if (x.compareTo(y) < 0) 42 if (y.compareTo(z) < 0) 43 return y; 44 else if (z.compareTo(x) < 0) 45 return x; 46 else 47 return z; 48 else if (z.compareTo(y) < 0) 49 return y; 50 else if (x.compareTo(z) < 0) 51 return x; 52 else 53 return z; 54 } 55 56}

投稿2020/06/26 17:19

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

guest

0

おーっと、ソート中にArrayListオブジェクトを作るとメモリ確保の時間がかかってクイックソートじゃなくなっちゃいますよ。配列もArrayListも大した変わらない(配列のほうが高速と思われ)ので、下記リンクのやり方でうまくいくと思います。

【Java】クイックソートのアルゴリズムのテスト

投稿2020/06/26 12:47

anndonut

総合スコア667

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

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

LouiS0616

2020/06/26 13:01

後学のためお聞きしたいことがあります。 『メモリ確保の時間がかかってクイックソートじゃなくなっちゃいます』というのは、 ・定義上、クイックソートでは無いということでしょうか? あるいは、 ・オーバーヘッドがかかって最早クイックでは無いよ、ということでしょうか?
anndonut

2020/06/26 13:43

後者ですね。
LouiS0616

2020/06/26 13:57

なるほど。 返信ありがとうございます。
nikaho

2020/06/26 14:17 編集

配列を使用した方が上手くいくことはわかっています。ネットに上がっているもののほとんどが配列を使用していますし... リンク先のプログラムも拝見しています。 その上で個人的なこだわりというか、ArrayListを使ってみたいんです。 なので早さもあまり気にしていません。構造がわかればいいんです。 そういった意味で「クイックソートを作りたい」ではなく「ArrayListを使った...」とタイトルに書いています。
anndonut

2020/06/26 22:15

そういうことだったんですね。すみませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問