JOI’95 予選 問題2 解答・解説

問題2 正解 (2点 = (a)(b)各1点)
      (a) C       temptable(j)
      tempをtable[i]としたものは正解ではない。

      (b) C       table[j]


 世の中にソーティングのアルゴリズムが数ある中で、挿入ソート法や 選択ソート法は最も単純なものの一つである。単純なだけに実行効率は よくない。すなわち、データの個数が n の場合 n2 に比例する時間 がかかる。とはいえ、n・log(n) に比例する時間しかかからないような 効率のよいアルゴリズムはいくつもあるが、データサイズが小さい場合には こういった単純なアルゴリズムで十分である。
 挿入ソート法や選択ソート法がどのような方法であるかはプログラム内に 丁寧な説明用コメントがあるのでここに繰り返す必要はないと思うが、 この機会にこれら以外の有用なソート法について勉強することを勧めたい。 特にクイックソートは再帰的ソート法の代表的なものであるから、 以下に簡単な説明をしておく。 (これ以外の有用なソート法に、マージソート、ヒープソート、2分探索木 を使うソート法などがある。)
 また、これらとは違う特殊なソート法の一つに基数ソート法や バケツソート法と呼ばれるものがある。基数ソート法の方法や 用途については、第1回日本情報オリンピックの問題4の解説を参照されたい。

クイックソ−ト

 以下のプログラムに記したように、「ある問題を解くのに、それを いくつかの(例えば、2つの)問題に分割して、それぞれを解く」 ということを再帰的に行なう手法を{\bf 分割統治法}といい、 良いアルゴリズムを設計するのに有効な考え方である。
   procedure solve(P); /* 問題Pを分割統治法で解く */
   begin                                            
       if Pのサイズが大きい then                    
          Pを小問題P1とP2に分割せよ;                   
          solve(P1); solve(P2);                        
          必要なら、solve(P1), solve(P2)の結果を統合せよ;
          else
          データサイズが小さいのでPを直接的な方法で解け 
       end if
    end

 この考え方によって設計されたソ−ト法であるクイックソ−トは、 実用的にも有効な方法である。余分なメモリを使わずにソーティングが行なえ、 データによっては効率が悪いこともあるものの、平均の実行時間は n・log(n) に比例する速いものである。

    procedure quicksort(P);
    /* 入力データPをソートしたい. 説明の都合上、Pは集合とする. */
    begin
        if Pの要素数>1 then
           Pの元を1つランダムに選び、それをsとする;
           P1←{ x∈P|x<s }; P2←P-P1; 
           quicksort(P1); quicksort(P2);
           quicksort(P1)の結果とquicksort(P2)の結果を合わせ全体の結果とせよ;
        end if
    end