再帰


今日の内容


マージソート (再帰版)

def merge(a, b)
  if a.length == 0 || b.length == 0
    a + b
  elsif a[0] < b[0]
    [a[0]] + merge(a[1..a.length-1], b)
  else
    [b[0]] + merge(a, b[1..b.length-1])
  end
end

def mergesort(a)
  if a.length <= 1
    a
  else
    last_index = a.length - 1
    half_index = last_index / 2
    merge(mergesort(a[0..half_index]),
          mergesort(a[half_index+1..last_index]))
  end
end

フィボナッチ数の計算

[問題 11.1]

  1. フィボナッチ数の計算を定義通りに再帰で計算する関数 fib_r(n) を作りなさい.
  2. fib_r(10),fib_r(20),fib_r(30),fib_r(40) の計算を行い,順番に計算時間が多くなる事を確認しなさい.
    特に,fib_r(40) ではかなり計算時間がかかるが,その理由を考察しなさい.

組合せの数

[問題 11.2]

  1. 組合せの数を計算する関数 combination(n,k) を再帰プログラムで作りなさい.
  2. アルゴリズムの正しさ (正当性) を示しなさい.
  3. アルゴリズムが終了すること (停止性) を示しなさい.

ユークリッドの互除法

[問題 11.3]

  1. ユークリッドの互除法を再帰プログラムで作りなさい.

ハノイの塔

[問題 11.4]

  1. 教科書にあるハノイの塔のアルゴリズムに従って, print 文で途中経過を出力する関数 hanoi(n,s,e,w) を再帰プログラムで作りなさい.
    ここで,n を円盤の個数,s を移動元の柱の番号,e を移動先の柱の番号,w を移動作業に利用する柱の番号とする.
    [例]
    irb(main):002:0> hanoi(3,1,2,3)
    1-th disk from 1 to 2
    2-th disk from 1 to 3
    1-th disk from 2 to 3
    3-th disk from 1 to 2
    1-th disk from 3 to 1
    2-th disk from 3 to 2
    1-th disk from 1 to 2
    => nil

クイックソートのアルゴリズムとその評価

クイックソートのプログラム

def quicksort(a)
  qsort(a, 0, a.length-1)
end

def qsort(a, from, to)
  if from < to
    pivot = (from + to) / 2
    med = a[pivot]
    l = from
    r = to
    while l <= r
      while a[l] < med
        l = l + 1
      end
      while a[r] > med
        r = r - 1
      end
      if l <= r
        a[l], a[r] = a[r], a[l]
        l = l + 1
        r = r - 1
      end
    end
    qsort(a, from, r)
    qsort(a, l, to)
  end
  a
end

[問題 11.5]

  1. クイックソートのプログラムを講義での説明を思い出しながら理解しなさい.
  2. クイックソートの平均計算量は O(n log n) であるが,最悪の場合には O(n2) となる.
    ソートする配列に整数 0 から 9 までがそれぞれ1個ずつ入っているとする.
    計算量が最悪となるのは,配列の要素がどのように並んでいるときなのかを具体例で示しなさい.

来週の予告


2012年11月30日作成
2012年12月7日改訂
伊知地 宏
Copyright (C) Hiroshi Ichiji, 2012. All rights reserved.