━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ データ構造・アルゴリズム論 確認問題13 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●問 (クイックソート) データ列 7, 5, 2, 1, 3 を配列に格納して,授業で扱った(教科書の) クイックソートで値を小さい順に並べ替える. (1) 関数 qsort(p, q) の呼び出し順を,各呼び出しでの実引き数の対 (p, q) の 列として((1,5), (2,3), (3,4), (5,5) などの形式で)表せ. ここで,p は配列の開始位置を,q は終了位置を表す. (2) 配列の変化を(授業で扱ったのと同じ形式で)示せ. ────────────────────────────────────── ●答 (クイックソート) (1) (1,5) (1,4) (1,2) (1,1) (2,2) (3,4) (3,3) (4,4) (5,5) (2) 実行前 [7, 5, 2, 1, 3] 途中結果 [3, 5, 2, 1][7] [1, 2][5, 3][7] [1][2][5, 3][7] [1, 2][5,3][7] [1, 2][3][5][7] [1, 2][3, 5][7] [1, 2, 3, 5][7] [1, 2, 3, 5, 7] [解説] 上記の解答 (1) の系列は,教科書のクイックソートの関数 qsort(p, n) の 呼び出し木(下図)を先行順に走査して得られる. (1,5) / \ (1,4) (5,5) / \ (1,2) (3,4) / \ / \ (1,1)(2,2)(3,3)(4,4) 教科書 p.39 の partition() では,分割対象の部分配列 a[p..q] の先頭要素 a[p] を 分割の基準値として使うことに注意する.上の例では 実行前の配列から基準値7,結果の1行目の左側の部分配列から基準値3, 結果の2行目先頭の部分配列から基準値1,結果の4行目中央の部分配列から基準値5, がそれぞれ選ばれる. なお,この解答では,手作業での実行を考えやすくするため, 配列が必ず二つの部分に分かれるように,教科書の qsort() を変更している. 具体的には,教科書 p.39 の再帰呼び出し qsort(a, p, j) を qsort(a, p, i-1) に変えた.元のままの場合,呼び出し (1,1) が (1,0) に変わる. これは,配列の a[1] から a[2] の範囲が,空列,a[1],a[2] の範囲の 三つの部分に分かれることを意味する. 上記の解答 (2) では,関数 qsort(p, q) の p < q の場合に (つまり,整列対象の要素数が2以上で,呼び出しの木の葉以外の節点で) 関数の実行直前と実行直後での配列の中身を示した. 整列対象の要素数が2以上の場合,整列対象の先頭要素を基準値とする値の大小で 配列を2分割し,前半部分と後半部分をそれぞれクイックソートで再帰的に整列する. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 授業のホームページ 山田 俊行 https://www.cs.info.mie-u.ac.jp/~toshi/