クイックソート
| 日本語 | 早並び替え |
| 英語 | quick sort、quicksort |
| ふりがな | くいっくそーと |
| フリガナ | クイックソート |
最速のソート。
ソートのアルゴリズムのひとつ。
「中間の値」を決めて、左右から入れ替えていき、分割、を繰り返すアルゴリズム。
最速だが、「すでにある程度並べられている」場合にあまり効果がないこと、安定ソートではないこと、といったデメリットもある。
クイックソートは、まず「中間の値」を決める。
「中間の値」は、実際に配列の中央にある値を取ることもあれば、全要素の中央値を使用する場合もある。
次に、左から値を見ていき、「中間の値」より大きな値があったら止まる。
同じく、右から値を見ていき、「中間の値」より小さな値があったら止まる。
そして、この2つの値を入れ替える。と、この時点で左に小さい値、右に大きな値が来る。
これを、左右が交差するまで続ける。すると、交差した位置の左には「中間の値より小さい値」、右には「中間の値より大きい値」が来る。
この位置で左右を分割し、それぞれで再び同じ処理を行う。
これを全て行うとソートが完了する。
Arraysクラスのsort()メソッドでプリミティブ型の配列をソートする場合、このアルゴリズムが用いられる。
アルゴリズムのテキストではもったいぶって最後に登場し、「最速」をうたっておきながら、状況によって処理速度にむらがあり、安定ソートではないといったデメリットがあるため、実用度という点ではあまり高くない。
ソートのアルゴリズムのひとつ。
「中間の値」を決めて、左右から入れ替えていき、分割、を繰り返すアルゴリズム。
最速だが、「すでにある程度並べられている」場合にあまり効果がないこと、安定ソートではないこと、といったデメリットもある。
クイックソートは、まず「中間の値」を決める。
「中間の値」は、実際に配列の中央にある値を取ることもあれば、全要素の中央値を使用する場合もある。
次に、左から値を見ていき、「中間の値」より大きな値があったら止まる。
同じく、右から値を見ていき、「中間の値」より小さな値があったら止まる。
そして、この2つの値を入れ替える。と、この時点で左に小さい値、右に大きな値が来る。
これを、左右が交差するまで続ける。すると、交差した位置の左には「中間の値より小さい値」、右には「中間の値より大きい値」が来る。
この位置で左右を分割し、それぞれで再び同じ処理を行う。
これを全て行うとソートが完了する。
Arraysクラスのsort()メソッドでプリミティブ型の配列をソートする場合、このアルゴリズムが用いられる。
アルゴリズムのテキストではもったいぶって最後に登場し、「最速」をうたっておきながら、状況によって処理速度にむらがあり、安定ソートではないといったデメリットがあるため、実用度という点ではあまり高くない。
参考サイト
// Sample.java
public class Sample
{
public static void main( String[] args )
{
// 出力する配列を用意します。
int[] ints = new int[]{ 4, 9, 3, 5, 8 };
for( int iF1 = 0; iF1 < ints.length; ++iF1 )
{
System.out.print( ints[iF1] + ", " );
}
System.out.println();
// 4, 9, 3, 5, 8,
// クイックソートします。
quickSort( ints );
for( int iF1 = 0; iF1 < ints.length; ++iF1 )
{
System.out.print( ints[iF1] + ", " );
}
System.out.println();
// 3, 4, 5, 8, 9,
}
/**
* クイックソートの「呼び出し元」。
*/
private static void quickSort( int[] array )
{
// 配列の先頭と最後を渡します。
quickSortImpl( array, 0, array.length - 1 );
}
/**
* クイックソートの実装。
* 再帰呼び出しされます。
*/
private static void quickSortImpl( int[] array, int firstPos, int lastPos )
{
// セパレータとなる値を取得。
int iSeparator = array[firstPos + ( ( lastPos - firstPos ) / 2 )];
// インデックス取得。
int iLeft = firstPos;
int iRight = lastPos;
// 無限ループ。
while( true )
{
// 左から見て、セパレータ以上の値まで移動。
while( array[iLeft] < iSeparator )
{
++iLeft;
}
// 右から見て、セパレータ以下の値まで移動。
while( iSeparator < array[iRight] )
{
--iRight;
}
if( iRight <= iLeft )
{
// 交差していたので抜けます。
break;
}
// 入れ替え。
int iTemp = array[iLeft];
array[iLeft] = array[iRight];
array[iRight] = iTemp;
// 入れ替え箇所を飛ばすため、ひとつ進めます。
++iLeft;
--iRight;
}
if( firstPos < iLeft - 1 )
{
// 左側の要素数が 1 よりも多ければ、
// 左側を再ソートします。
quickSortImpl( array, firstPos, iLeft - 1 );
}
if( iRight + 1 < lastPos )
{
// 右側の要素数が 1 よりも多ければ、
// 右側を再ソートします。
quickSortImpl( array, iRight + 1, lastPos );
}
}
}
public class Sample
{
public static void main( String[] args )
{
// 出力する配列を用意します。
int[] ints = new int[]{ 4, 9, 3, 5, 8 };
for( int iF1 = 0; iF1 < ints.length; ++iF1 )
{
System.out.print( ints[iF1] + ", " );
}
System.out.println();
// 4, 9, 3, 5, 8,
// クイックソートします。
quickSort( ints );
for( int iF1 = 0; iF1 < ints.length; ++iF1 )
{
System.out.print( ints[iF1] + ", " );
}
System.out.println();
// 3, 4, 5, 8, 9,
}
/**
* クイックソートの「呼び出し元」。
*/
private static void quickSort( int[] array )
{
// 配列の先頭と最後を渡します。
quickSortImpl( array, 0, array.length - 1 );
}
/**
* クイックソートの実装。
* 再帰呼び出しされます。
*/
private static void quickSortImpl( int[] array, int firstPos, int lastPos )
{
// セパレータとなる値を取得。
int iSeparator = array[firstPos + ( ( lastPos - firstPos ) / 2 )];
// インデックス取得。
int iLeft = firstPos;
int iRight = lastPos;
// 無限ループ。
while( true )
{
// 左から見て、セパレータ以上の値まで移動。
while( array[iLeft] < iSeparator )
{
++iLeft;
}
// 右から見て、セパレータ以下の値まで移動。
while( iSeparator < array[iRight] )
{
--iRight;
}
if( iRight <= iLeft )
{
// 交差していたので抜けます。
break;
}
// 入れ替え。
int iTemp = array[iLeft];
array[iLeft] = array[iRight];
array[iRight] = iTemp;
// 入れ替え箇所を飛ばすため、ひとつ進めます。
++iLeft;
--iRight;
}
if( firstPos < iLeft - 1 )
{
// 左側の要素数が 1 よりも多ければ、
// 左側を再ソートします。
quickSortImpl( array, firstPos, iLeft - 1 );
}
if( iRight + 1 < lastPos )
{
// 右側の要素数が 1 よりも多ければ、
// 右側を再ソートします。
quickSortImpl( array, iRight + 1, lastPos );
}
}
}
// Sample.java
public class Sample
{
public static void main( String[] args )
{
// 出力する配列を用意します。
int[] ints = new int[]{ 4, 9, 3, 5, 8 };
for( int iF1 = 0; iF1 < ints.length; ++iF1 )
{
System.out.print( ints[iF1] + ", " );
}
System.out.println();
// 4, 9, 3, 5, 8,
// クイックソートします。
quickSort( ints );
for( int iF1 = 0; iF1 < ints.length; ++iF1 )
{
System.out.print( ints[iF1] + ", " );
}
System.out.println();
// 3, 4, 5, 8, 9,
}
/**
* クイックソートの「呼び出し元」。
*/
private static void quickSort( int[] array )
{
// 配列の先頭と最後を渡します。
quickSortImpl( array, 0, array.length - 1 );
}
/**
* クイックソートの実装。
* 再帰呼び出しされます。
*/
private static void quickSortImpl( int[] array, int firstPos, int lastPos )
{
// セパレータとなる値を取得。
int iSeparator = array[firstPos + ( ( lastPos - firstPos ) / 2 )];
// インデックス取得。
int iLeft = firstPos;
int iRight = lastPos;
// 無限ループ。
while( true )
{
// 左から見て、セパレータ以上の値まで移動。
while( array[iLeft] < iSeparator )
{
++iLeft;
}
// 右から見て、セパレータ以下の値まで移動。
while( iSeparator < array[iRight] )
{
--iRight;
}
if( iRight <= iLeft )
{
// 交差していたので抜けます。
break;
}
// 入れ替え。
int iTemp = array[iLeft];
array[iLeft] = array[iRight];
array[iRight] = iTemp;
// 入れ替え箇所を飛ばすため、ひとつ進めます。
++iLeft;
--iRight;
}
if( firstPos < iLeft - 1 )
{
// 左側の要素数が 1 よりも多ければ、
// 左側を再ソートします。
quickSortImpl( array, firstPos, iLeft - 1 );
}
if( iRight + 1 < lastPos )
{
// 右側の要素数が 1 よりも多ければ、
// 右側を再ソートします。
quickSortImpl( array, iRight + 1, lastPos );
}
}
}




