2012年12月25日火曜日

クイックソート

クイックソート
 
 
名前の通り早くソートすることが可能なソートアルゴリズムです。
 
 
特に要素が長い時に効果を発揮します。
自分もバブルソートや挿入ソートと比べてその速さに驚きました。
では、内容を見ていきたいと思います。
 
まず、以下の数列データがあるとします。
 
 
5 14 10 15 13 4 2 7 19 12
 
 
要素数は10、でランダムに並んでいます。
これをクイックソートを使用して、昇順にソートしていきたいと思います。
 
 
まず、この10個の要素の中からひとつの要素を選びます。
ここでは、要素数の中間の値であるものを選びたいと思います。
コードにすると、
 
(要素の開始位置 + 要素の終了位置) / 2
 
つまり、
 
(0 + 9) / 2 = 4
 
4番目の要素が中間値となります。
つまり、13です。
そして、この13を基準値にしてデータ数列をソートしていきます。
 
ちなみに基準となる数字つまり軸となるものをピボットと呼びます。
このピボットを赤数字で示します。
 
 
5 14 10 15 13 4 2 7 19 12
 
 
次は、このピボットを昇順にソートした時にくる位置に挿入します。
 
その為に以下の方法を使います。
 
 
データ数列の先頭からピボット以上のデータを探し、
またデータ数列の末尾からピボット以下のデータを探して、その値が見つかった場合に、
その値同士を交換していきます。
 
そして、先頭と末尾の捜査がぶつかるまでこの操作を続けます。
 
では、先頭から始める捜査を緑数字で、末尾から始める捜査を青数字で表します。
 まずは、先頭から始める捜査に関して見ていきます。
 
 
5 14 10 15 13 4 2 7 19 12
 
 
5は13以上ではないので、次に進めます。
 
 
5 14 10 15 13 4 2 7 19 12
 
 
14は13以上なので14は交換すべき要素となります。
次は、末尾から捜査します。
 
 
5 14 10 15 13 4 2 7 19 12
 
 
12は13以下なので、12は交換すべき要素となります。
それでは交換しましょう。
 
 
5 12 10 15 13 4 2 7 19 14
 
 
要素が交差するまで作業を続けるので、また、先端から捜査していきます。
 
 
5 12 10 15 13 4 2 7 19 14
 
 
10は13以下ですので、次の要素の見ていきます。
この作業を続けていくわけです。
 
 
5 12 10 15 13 4 2 7 19 14
 
 
15は13以上ですので、交換要素がきまりました。
次は末尾から捜査します。
 
 
5 12 10 15 13 4 2 7 19 14
 
5 12 10 15 13 4 2 7 19 14
 
5 12 10 7 13 4 2 15 19 14
 
 
末端から検索して7に行き着きました。
そして、先頭要素と末尾要素を交換しました。
さらに続けます。
 
 
5 12 10 7 13 4 2 15 19 14
 
 
ピボットである13が交換要素となりました。
では末尾を捜査しましょう。
 
 
5 12 10 7 13 4 2 15 19 14
 
5 12 10 7 13 4 2 15 19 14
 
5 12 10 7 2 4 13 15 19 14
 
 
末尾から捜査した2と13を交換しました。
では、先頭から捜査します。

 
5 12 10 7 2 4 13 15 19 14
 
5 12 10 7 2 4 13 15 19 14
 
 
先頭からの要素を進めて、13が交換すべき要素となりますが、先頭と末尾が交差してしまったので、ここでの作業は終わりです。
 
 
次はピボット13を中心にして、左のデータ数列と右のデータ数列を分けて、
上記でやった作業を行います。
 
この作業を続けて、整列すべきデータ数列が1要素になるまで、
行えば昇順にソートされます。
つまり、


5 12 10 7 2 4 13 15 19 14

 
ピボットより左のデータ数列とピボットより右のデータ数列に対してそれぞれ別に、
ピボットを決め、上記で行ったソートを行い、ソートが完了したらそのデータ数列のピボットを基に、
ソートを行う。
 
これを繰り返して、整列すべきデーター数列の要素が1になったらソートの終了です。
 
 
では、ピボット13の右側のデータ数列について見ていきます。

 
15 19 14

 
ピボットを決める条件はデーター数列の真ん中の値ですから、
 
 
(0 + 2) / 2 = 1
 
 
1番目の要素を基準値にするので、19がピボットとなります。
では、左側から捜査していきます。
 
 
15 19 14
 
15 19 14
 
 
捜査していった結果ピボット自身が交換対象となりました。
では、末端から捜査しましょう。
 
 
15 19 14
 
15 19 14

15 14 19
 
 
14と19を交換しました。
その後交差するので、ここでのソートは終了です。

次に、ピボットである19の左右を見ますが、左のデータ数列のみで、
右のデータ数列は要素がないので終了です。

では、左のデータ数列を見ていきましょう。
 

15 14
 

ピボットは


(0 + 1) / 2 = 0


0番目の要素15がピボットになります。
では左側から捜査します。


15 14

15 14

14 15


ピボットが交換対象となり、14は15以下なので、14と15を交換します。
つぎは、交差するのでここで捜査終了です。
また、ピボットの左側の要素が1となったので、右側のソートも終了します。

ということで、以下のようなデータ数列になります。


5 12 10 7 2 4 13 14 15 19


右側のソートが終了しています。
次は、左側に関して同じようにソートしていけば、昇順にソートされることがわかります。

今回は、ピボットを真ん中の値としましたが、先頭の値をピボットとしてもいいですし、
ソートに関して、効率のよい値をピボットにするのがベストです。

では、最後にc++のソースコートを載せます。


/*
 array = ソートしたいデータ
 begin = 要素の最初
 end = 要素の末尾
*/
void QuickSort(int array[], int begin, int end)
{
 int i = begin;
 int j = end;
 int pivot;
 int temp;
  
 pivot = array[ ( begin + end ) / 2 ];  // 中央の値をpivotにする
 
 while( 1 )
 {
  while( array[i] < pivot ){ ++i; }  /* 枢軸以上の値が見つかるまで右方向へ進めていく */
  while( array[j] > pivot ){ --j; }  /* 枢軸以下の値が見つかるまで左方向へ進めていく */
  if( i >= j )break;  // 軸がぶつかったらソート終了
  
  // 入れ替え
  temp = array[i];
  array[i] = array[j];
  array[j] = temp;
  i++;
  j--;
 }
 
 // 軸の左側をソートする
 if( begin < i - 1 ){ QuickSort( array, begin, i - 1 ); }
 // 軸の右側をソートする
 if( j + 1 < end ){ QuickSort( array, j + 1, end ); }
}

 

2012年12月21日金曜日

挿入ソート

挿入ソートとは

挿入ソートは、データ列の中で、ソートされた部分とまだソートされていない部分に分けて、 ソートされているデータ列に新たな未ソート部分の値を挿入していくソート方法です。

では、 挿入ソートを例題をあげて解説してみます。

挿入ソートの例題

まず次のようなデータがあるとします。

20 4 18 5 1

このデータを挿入ソートを使って昇順に並べ替えてみたいと思います、

赤数字がソート対象となり、青数字が未ソート部分で、緑数字ソートが終わった部分とします。

まず、1番目と2番目の要素に着目してソートを行います。

20 4 18 5 1
4 20 18 5 1

まず、最初の20と4が対象となり、20 > 4なので、左右を入れ替えます。

次に3番目の要素である18に着目してソートを行います。

4 20 18 5 1
4 20 18 5 1

20 > 18 なので、18の位置を決定するために、さらに左の要素を見ることになります。

次に4,18に着目します。

20 18 5 1
4 18 20 5 1

4 < 18なので、先程入れ替え対象となった、2番目の要素20の位置に18を挿入して、 次の要素を見ていきます。

次は4番目の要素である5に着目してソートを行います。

4 18 20 5 1
4 18 20 5 1
4 18 20 5 1
4 5 18 20 1

1.
まず、20 > 5なので3番目の要素が挿入位置となります。

2.
18 > 5なので、2番目の要素が挿入位置となります。

3.
4 < 5なので、2番目の位置が挿入位置となりました。

4.
2番目の位置に18を挿入します。

次は、最後の要素1に着目して上記の操作を行います。

こうした手順でソートすることを挿入ソートといいます。

では、最後にc++でソースを載せます。

// 挿入ソート
void InsertSort(int x[],int n){
 int temp;
 for (int i = 1; i < n; i++) {
  for (int j = i-1; j >= 0; --j) {
   if (x[j] > x[j+1]) {
    temp = x[j];
    x[j] = x[j+1];
    x[j+1] = temp;
   } else break;
  }
 }
}

2012年12月20日木曜日

バブルソート

バブルソート


隣合う数字の大小を比較しながら整列させるソートのことです。
実装する中身が

n × n

となるためにO(n^2)となるので、整列のアルゴリズムとしては遅いようです。
なので、要素が短いという条件意外では使えそうもないです。



では、例を見ていきます。


初期データ5個の整数を持つとします。


80 20 17 41 4


これをバブルソートを利用して、昇順にソートしていく過程を見ていきます。
赤色がソート対象となる値で、青がソート完成した値です。

80 20 17 41 4

20 80 17 41 4

20 17 80 41 4

20 17 41 80 4

20 17 41 4 80


20 17 41 4 80

一回目のforループが終わって末端に最大値が来ました。

次はまた、最初の数値から見て、末端を除いて値を交換していきます。


20 17 41 4 80

17 20 41 4 80

17 20 41 4 80

17 20 4 41 80

17 20 4 41 80




5列目と4列目が固定されました。
後は同じように整列を続けます。


では、これをc言語のコードにしてみます。
/*
 x[] = sortしたい配列
 n = 配列要素の最大数
*/
void BubbleSort(int x[ ], int n)
{
 int temp;
 for (int i = 0; i < n; ++i) {
  for (int j = 1; j < n - i; j++) {
   if (x[j - 1] > x[j]) { 
    temp = x[j - 1];
    x[j - 1] = x[j];
    x[j]= temp;
   }
  }
 }
}
 
以上で終わります。