ならべる——差しこみで

よみもの+手を動かす時間:およそ25分

速さの裏には、そろえた人がいる

前のレッスンの二分探索は、半分をまるごと捨てられる手順でした。ただしあの速さには前提があります——数列が、あらかじめそろっていることです。

では、そのそろえる仕事は誰がやるのでしょう。バラバラの列を順番どおりにならべる仕事を、プログラミングの世界ではソートと呼びます。今日はその仕事の、いちばん人間らしい手順から始めます。

あなたが書いた手順に、名前がつきます

レッスン1を思い出してください。コースの冒頭で、実験室が数の列をならべる様子を「中身の説明ぬきで」再生しました。そして演習で、あなたはトランプの手札をならべる自分の手順を、曖昧さのない日本語で書きました。

あのとき再生されたものと、あなたが書いたものは、同じ手順です。名前を挿入ソート(そうにゅうソート)——差しこんでならべる手順、といいます。今日は名前だけでなく、回数の物差しもあてます。

手順を、ことばにしなおす

トランプの手つきを、曖昧さのないことばに直すとこうなります。

  1. 左はしの1枚は、それだけで「そろっている」とみなす
  2. 2枚目から順に1枚ずつ手に取る
  3. 手に取った1枚を、左のそろった列の正しい位置に差しこむ。位置をさがすときは、すぐ左の数とくらべて、大きい数を1つずつ右へずらす
  4. 最後の1枚まで、これをくりかえす

再生して、ずらして差しこむ動きに注目してください。差しこむ場所をあけるために、大きい数たちが1つずつ右へ動いていきます。

差しこみでならべるくらべた回数 0
528193

ならべる前。左はしの1枚は、それだけで「そろっている」

1 / 22 場面

どの瞬間も、左側はつねに「そろった列」です。手に取った1枚の行き先だけを考えればよい——これが、この手順が人間の手に自然になじむ理由です。

回数は、列の「乱れぐあい」で決まる

数列を打ちかえて、くらべた回数を観察してみてください。同じ6個でも、ならびかたで回数がまるで違います。

  • そろい済み [1, 2, 3, 4, 5, 6]5回。どの数も「すぐ左が自分以下」を確認するだけで、1回もずらさずに終わります
  • 逆順 [6, 5, 4, 3, 2, 1]15回。手に取るたびに、左のぜんぶとくらべて、ぜんぶずらすことになります

最良の場合は6個で5回——個数より1つ少ない回数で、確認だけして終わります。最悪の場合は15回。レッスン2で学んだとおり、手順の力くらべに使うのは最悪の場合のほうです。

倍にしたら、ほぼ4倍

では、逆順の枚数を倍にしてみます。[12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] を実験室に打ちこむと、66回です。

6枚で15回、12枚で66回。枚数が倍になると、最悪の回数はほぼ4倍になりました。比例なら「倍になったら倍」のはずですから、これは比例より急な、別のかたちです。

このかたちは n²(エヌの2乗) と呼ばれます。正体は「毎回、左のぜんぶとくらべてぜんぶずらす」の積み重ねです。かたちどうしの本格的なくらべあいはレッスン6でやるので、今日は「比例より急な坂に出会った」とだけ覚えてください。

挿入ソートの名誉のために

ここまで読むと「遅い手順」に見えるかもしれません。でもそれは、最悪の場合だけを見た言い分です。

ほぼそろっている列に、この手順はめっぽう強いのです。12枚のうち最後の2枚だけが入れかわった [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 11] を試すと、12回で終わります。同じ12枚でも、逆順の66回とは別世界です。

演習:逆順7枚を予想する

逆順の7枚 [7, 6, 5, 4, 3, 2, 1] をならべると、くらべる回数は何回になるでしょう。まず紙の上で予想してから、実験室に打ちこんで確かめてください。

ヒント1(考え方)

逆順では、手に取った1枚は左のぜんぶとくらべることになります。2枚目は1回、3枚目は2回、4枚目は3回——この調子で、最後の7枚目まで足してみてください。

こたえ

1 + 2 + 3 + 4 + 5 + 6 = 21回です。6枚の15回は 1+2+3+4+5、12枚の66回は 1+2+…+11。最悪の回数の正体が「1からの足し算」だと分かると、枚数が倍でほぼ4倍になる理由も、この足し算が長く・高くなることだと見えてきます。

このレッスンで分かったこと

  • そろえる仕事をソートと呼ぶ。二分探索の速さは、この仕事の上に立っている
  • 挿入ソート:左のそろった列に、1枚ずつ正しい位置へ差しこむ。レッスン1であなたが書いた、あの手順
  • 回数は乱れぐあいで決まる——そろい済み6個で5回、逆順なら15回
  • 逆順12個は66回。枚数が倍で最悪はほぼ4倍——比例より急な のかたち
  • ほぼそろった列にはめっぽう強く(12個で12回)、小さい列でも現役。「遅いソート」と切り捨てない