見出し画像

JavaScriptで学ぶアルゴリズム③[ソートアルゴリズム⑴]-バブルソート, 選択ソート,挿入ソート

外資系企業でソフトウェアエンジニアをしております、タロイモと言います。今日もよろしくお願いします。

前々回から、O(n)とO(1)、O(log n)アルゴリズムの紹介をしてきました。

今回はソートアルゴリズムについて紹介いたします。

1. ソートとは

ソートとは、与えられたデータ(数字)を小さい順に並べ替えることです。

日本語に直すと「整列」という言葉で表すことができます。

2. O(n^2)

O(n^2)はデータ量nが多いほど、処理が指数関数(y = x^2)のように増えていきます。

そのため、O(n^2)アルゴリズムを使う際には、データ数に応じて膨大な処理量になることがあるため要注意です。

できるならば、O(n), O(log n), O(1)アルゴリズムの関数を使うべきです。

スクリーンショット 2020-08-29 12.40.02


バブルソート

右から左に向かって、隣り合っている数字を比較し、小さい順に入れ替えていくのが「バブルソート」です。

画像で表すとこんな感じになります。

①バラバラに並んだ数字データを右から比較し、
2と5は小さい順なのでそのままでOK

スクリーンショット 2020-08-29 12.21.21

②6と2は小さい順ではないので、、

スクリーンショット 2020-08-29 12.21.26


入れ替えます。

スクリーンショット 2020-08-29 12.21.53

③7と2も小さい順でないので、、

スクリーンショット 2020-08-29 12.23.29

交換し、その後の数字も順々に入れ替えていきます。

スクリーンショット 2020-08-29 12.24.00

スクリーンショット 2020-08-29 12.24.23

④これで2が1の右に来たので、1,2をソート済みとします。
次にまた右から5と6を小さい順に比較し、、みたいな感じで
1,2,3,4,5,6,7,8と言う順番になるように繰り返します。

スクリーンショット 2020-08-29 12.24.42


バブルソートをJavaScriptで表すと以下のようになります。

let array = [1, 4, 3, 8, 7, 6, 2, 5];

function bubble_sort(array) {
 //配列の数だけループする
 for (let i = 0; i < array.length; i++) {
   //配列の左側から比較していく
   for (let j = array.length; i < j; j--) {
     //右側の数より左側の数が大きい場合は入れ替える。
     if (array[j] < array[j - 1]) {
       let tmp = array[j - 1];
       array[j - 1] = array[j];
       array[j] = tmp;
     }
   }
 }
}

bubble_sort(array);

console.log(array); // [1, 2, 3, 4, 5, 6, 7, 8]

ただJavaScriptにはsort関数が用意されているので、わざわざ使う必要がありません。

sort関数では返り値がプラスのとき(aがbより大きいとき)、aをbの後ろに並べ替えます。
反対に返り値がマイナスのとき(bがaより大きいとき)、aをbの前に並べ替えます。

let array = [1, 4, 3, 8, 7, 6, 2, 5];

array.sort(
 function(a, b) {
   return a - b;
 }
);

console.log(array); // [1, 2, 3, 4, 5, 6, 7, 8]


選択ソート

あるデータの中で線形探索で最小値を見つけ、その最小値を一番左の数字と入れ替えることを繰り返すのが「選択ソート」です。

画像で表すとこんな感じになります。

①バラバラに並んだ数字データを線形探索で、最小値を探します。
今回は1が最小値になります。

スクリーンショット 2020-08-29 13.27.37

②最小値1を一番左にある3と交換します。
これで1はソート済みとなります。

スクリーンショット 2020-08-29 13.31.04

③次もまた、線形探索で最小値を探します。
ソート済みの1は除外して線形探索します。
今回は2が最小値となります。

スクリーンショット 2020-08-29 13.31.37

④2と一番左にある4を交換します。

スクリーンショット 2020-08-29 13.33.42

⑤2がソートされたら、同様に繰り返します。今回は最小値3が一番左にあるので交換しません。
このように、最小値と一番左にある数字を交換し、
1,2,3,4,5,6,7,8の順番になるまで繰り返します。

スクリーンショット 2020-08-29 13.32.48

選択ソートをJavaScriptで表すと以下のようになります。

let array = [1, 4, 3, 8, 7, 6, 2, 5];

function selection_sort(array) {
 //配列の数だけループする
 for (let i = 0; i < array.length; i++) {
   //最小値を一番右の値と仮定
   let min = array[i];
   //最小値の配列の添字も保存
   let k = i;
   //配列の隣の位置から最後まで最小値との比較を繰り返す。
   for (let j = i + 1; j < array.length; j++) {
     //最小値の方が大きかったら、その値が最小値になる。
     if (min > array[j]) {
       min = array[j];
       //最小値のある添字も更新
       k = j;
     }
   }
   //現段階の最小値を仮保存
   let tmp = array[i];
   //実際の最小値を一番左へ
   array[i] = array[k];
   //現段階の最小値を交換
   array[k] = tmp;
 }
}

selection_sort(array);

console.log(array); // [1, 2, 3, 4, 5, 6, 7, 8]


挿入ソート

データの左側から順番にソートしていくのが「挿入ソート」です。

左側の値をソート済みにし、残りのソートしていない一番左の値とソート済みの値比べ、小さい順になるように、適切な場所に挿入します。

画像で表すとこんな感じになります。

①バラバラな順番で並んでいるデータがあるとして、
一番左の7をソート済みとします。

スクリーンショット 2020-08-29 13.49.24

②7をソート済みにしたら、次にソートしていない一番左の値2と7を比較します。

スクリーンショット 2020-08-29 13.51.41

2は7より小さいので、7の左側に置きます。
これで2つの数がソート済みになりました。

スクリーンショット 2020-08-29 13.52.04

③同様に、ソート済みのデータとソートしていない一番左の値1を比較します。

スクリーンショット 2020-08-29 13.53.33

1は一番小さいので、一番左に配置します。
これを全てのデータが小さい順(1,2,3,4,5,6,7,8)になるまで繰り返して、ソートしていきます。

スクリーンショット 2020-08-29 13.54.03


挿入ソートをJavaScriptで表すと以下のようになります。

let array = [1, 4, 3, 8, 7, 6, 2, 5];

function insertion_sort(array) {
 for (let i = 1; i < array.length; i++) {
   let j;
   //挿入する値をいったん変数に保存
   let tmp = array[i];
   //整列ずみのどの部分に挿入するか、整列済みの分だけ整列済みの大きい方から順にループ
   for (j = i - 1; j >= 0; j--) {
     //挿入する変数tmpが、整列済みの変数array[j]より大きい場合、そのままループから抜け出すbreak
     if (tmp > array[j]) {
       break;
     } else {
       //挿入する変数tmpが整列済みの変数array[j]より小さい場合、array[j]の添字が一個増えたところにarray[j]の値を保存。
       array[j + 1] = array[j];
     }
   }
   //breakした場合、挿入する値はarray[j+1]に
   array[j + 1] = tmp;
 }
}

insertion_sort(array);​

console.log(array); // [1, 2, 3, 4, 5, 6, 7, 8]​


お疲れ様でした。

次回は、マージソートについて解説していこうと思います。

今回もご精読ありがとうございました。

よろしければサポートお願いします! サポートは、サービスの開発・改良や、記事を書く際の素材費とさせていただきます。 少しでも有益な情報発信をしていけるよう努めてまいります。 是非とも応援よろしくお願いします!!!🙇‍♂️