━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
データ構造・アルゴリズム論 確認問題3
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●問 (リストの基本操作)

(1) リスト l1 = [10, 20, 30, 40, 50] に対して,次の基本操作を順に実行した後の
  リスト l2 が何かを答えよ.

        insert(l1, 1, 0);
        delete(l1, 5);
        l2 = sub(l1, 3);

(2) リスト l = [10, 20, 30] に対して次のプログラムを実行した後の val の値が
  何かを答え,その値が何を意味するかを説明せよ.

        int val = 0;
        while (! empty(l)) {
            val += access(l, 1);
            delete(l, 1);
        }

──────────────────────────────────────

●答 (リストの基本操作)

(1) l2 = [20, 30, 50]
(2) val の値は 60.これは,リスト l の要素の総和を表す.

[解説]

(1) リスト l1 は insert() 実行後に [0, 10, 20, 30, 40, 50] となり,
delete() 実行後 に [0, 10, 20, 30, 50] となる.

この問題で使う三つの基本操作は,次の機能をもつ.
        insert(l, k, a) … リスト l の位置 k に要素 a を挿入する
        delete(l, k) … リスト l の位置 k の要素を削除する
        sub(l, k) … リスト l の位置 k 以降の部分リストを返す
なお,列の先頭位置を(0でなく) 1 で表していることに注意する.

(2) ループの実行前と反復ごとの l と val は,次のように変化する.

        回数    l               val
        -----------------------------------------
        0       [10, 20, 30]    0
        1       [20, 30]        10 (=  0 + 10)
        2       [30]            30 (= 10 + 20)
        3       []              60 (= 30 + 30)

反復ごとに,リストの先頭要素が val に加算され,リストから取り除かれる.
プログラムの動作が分かりにくい場合には,この問題で考えたように,
小さな具体例での各変数の値の変化を考えるとよい.
なお,基本操作 delete() が削除値を返す機能をもつなら,直前の access() が不要で,
ループ中に val += delete(l, 1); だけを実行すればよい.

このアルゴリズムは,基本操作を組み合わせて,より複雑な処理を実現する例である.
列に対する基本操作としては,空判定,(先頭要素の)参照,(先頭要素の)削除,
の三つが使われている.これらを使って,列の走査(一つずつ全ての要素の処理)を
しながら総和を計算するという,より複雑な処理が実現されている.

列は,先頭要素と残りのリストとに分けて,効率的に反復処理できることが多い.
処理位置を限定して効率化する考え方は,スタックやキューなどのデータ構造で
活用される.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
授業のホームページ

山田 俊行
https://www.cs.info.mie-u.ac.jp/~toshi/