メインコンテンツへスキップ
見出し画像

【紙芝居トレース】単方向リストの作成/追加(FEBサンプル問題2問03, 基本情報技術者試験, 科目B, 午後, 擬似言語, オブジェクト指向)擬似言語⑬Aの1

    このNoteでは「単方向リスト」をオブジェクト指向で実現した擬似言語問題をガチでトレースします。>【FEB】サンプル問題2問03のNote

    画像

    このNoteはシリーズの予定です。

    1. 単方向リストの作成/追加
      >【FEB】サンプル問題2問03のNote

    2. 単方向リストの削除
      >【FEB】サンプル問題1問10のNote

    3. 単方向リストの挿入(企画中*)

    4. 双方向リストの作成/追加(作成中*)

    5. 双方向リストの削除(作成中*)

    6. 双方向リストの挿入(作成中*)
      >【FEA】令和05年問02のNote

    FE科目Bに単方向リストが出てるので学習は当然として。科目Aに双方向リストが出てるので、科目Bに出る備えもしたいと考えました。

    しかし単方向リストを「何となく正解できる」程度では、双方向リストのトレースはできません。単方向リストをガチでトレース/理解して、双方向リストの理解に挑戦する教材を作ろうと思い立ちました。

    少しでも学習のお役に立てたら嬉しいです。

    それでは始めましょう!


    >全Noteへのリンク(FE節)
    ※科目Aのテーマ別対策、科目B対策、旧FE午後(セキュリティ)など沢山作りました!

    【NOTICE】著作権を侵害には即座に法的措置をしています。人格否定もブロックなどの自衛手段を行います。私は1個人であり、公人ではありません。プライベート時間の全てを費やして作成してきました。ご理解頂ける方のみ、ご活用されると嬉しいです🫠


    今回の全体像

    単方向リストのクラスListElementと、リストを構築するappend関数のトレースを行います。

    クラスと関数は、>【FEB】サンプル問題2問03のNote に出ています。作るリスト(A→K→T)は、今Noteシリーズの最終ゴール >【FEA】令和05年問02のNote と同じ。

    画像

    単方向リスト(A→K→T)の作成が目的。メイン処理が実行され。大域宣言、関数呼び出し3回を経てプログラムは終了します。

    FEにクラスの擬似言語は書かれませんが、下記な感じかな。

    クラス ListElement
      メンバ変数
        文字型: val
        ListElement:next  /* 初期状態は未定義である */
    
      コンストラクタ ListElement(文字型: qVal)
        val ← qVal

    今回トレースする擬似言語。

    〔プログラム〕
      大域: ListElement: listHead ← 未定義の値
      append("A")
      append("K")
      append("T")
    
      ○append(文字型: qVal)
        ListElement: prev, curr
        curr ← ListElement(qVal)
        if (listHead が 未定義である)
          listHead ← curr
        else
          prev ← listHead
          while (prev.next が 未定義でない)
            prev ← prev.next
          endwhile
          prev.next ← curr
        endif

    append関数は>【FEB】サンプル問題2問03のNote のまま。空欄も正答で埋めてます。




    大域宣言

    下準備として「listHead」変数(ポインタ変数)を準備します。「大域」宣言なので、プログラム全体で共用します。>【2分×30節で読める】擬似言語の教科書Note㉚

    画像

    この後に、append関数を3回呼び出します。
    append("A") append("K") append("T")
    次節からトレースします。




    append("A")

    append("A")をトレースします。

    最初の1~2行が擬似言語/プログラム。3行目以降に、変数/メモリ(データ)の作成状況、ポインタ変数がメモリ位置を指している状況を矢印図示しました。「※」は理解を助けるコメントを書いてます。

    画像

    擬似言語1行1行で変化した部分に色を付けてます(青, 緑, 水色)。注目/注意すべき点も(緑, 赤)。

    画像

    listHeadにAが記録されてるアドレスが格納されて、リストに1個目の要素が追加されます。

    画像

    append関数が終わったので局所宣言のprev, currは喪失。listHeadは大域宣言なので残ります。

    画像

    リストに”A”が追加されたので、次は"K"を追加します。次節ではappend("K")をトレースしましょう。




    append("K")

    append("A")で一度通ったので軽めに描きつつ、新しい/細かい解説を追加しますね。

    append("K")の一行目はappend("A")と同じ。そりゃ同じ宣言ですから。ただし、今回作ったprev, currは、append("A")で作ったprev, currとは別物(※)。

    画像

    "K"のデータを作りメモリに配置します。アドレス300は偶然です。Aのアドレス100も偶然。

    画像

    次のif文判定。append("A")と違います。append("A")では真Trueでしたが、今回は偽False。listHead(リスト先頭)には"A"のアドレスが格納されてますからね。

    画像

    初めて実行されたif-False(else)。prevはappend("A")で使わなかったけど、今回使います。今後のご活躍に期待。

    画像

    if-false内にwhileあり。ループをすべきか判定します。「~でない」が真Trueなので、言葉がややこいですね。

    画像

    「~でない(真)、ではない」ので偽False。while文内は実行せず。実行するケースも見たいですね。

    while文を抜け直下、if-False(else)の最後の1行。

    画像

    currが指してる”K”を、prev.nextも指します。prevは現在"A"を指してる。"A"が記録されてるオブジェクトの属性「.next」に”Kへのアドレス”を格納。

    append("K")終了。

    ※skipOK。currとprev.nextが同じ働きをしてます。宣言をみると、どちらも「ListElement型」。どちらも「ListElement型データを指すポインタ変数」なのです。上手くできるなぁと個人的に感動しました。


    局所だったprev, currは喪失。大域listHeadとリスト(A→K)は残ります。append("A")終了後と同じ。

    画像

    次はappend("T")で、リストがA→K→Tになるのを確認します。




    append("T")

    一行目は宣言なので同じ。

    画像

    リストに追加したい”T”データ、のオブジェクトを生成。

    画像

    リストは存在してる(listHeadが指してる)ので、今回もif-False(else)を実行。

    画像

    else文でprevの指し先が決まり。前回append("K")と一緒。

    画像

    今回はwhile文内も実行。やったぁ!

    画像

    while文内の初実行。prevの指し先が変わります。

    画像

    while文の2回目を実行すべきか判定。実行しなくて良し。

    画像

    現リストを最後まで辿るループだったんですね。

    while文抜け、if-False(else)のラスト1行。append("K")と同じ処理。でもprevの状況が違う。

    画像

    prev.nextが未定義(=リスト最後)でしたが、curr(="T"の位置)を格納させたので、リストに要素3番目が追加されました。

    append("T")終了。局所は消えて、大域たちが残る。

    画像

    以上、一行一行トレースできました。

    ご自分でも、擬似言語を一行一行読みながら、状況を描いて見てくださいね。




    フロー全体の把握

    前節まで1行1行トレースしたので、全体の流れをチェック。各部の役割とか、今回確認できなかった部分があるか。

    画像

    全行/全分岐/全命令が実行できてます。

    append("A")が、if文Trueルート。
    append("K")が、if文False+while0回ルート。
    append("T")が、if文False+while1回ルート。
    全ルート巡れたので良かった。

    もし実行確認できなかった行/ルートがあったら、「何のために必要なのかなぁ」と考えて、別値でトレースします。それが勉強。

    なお、次回delNode()関数でやる模様。授業の時間枠じゃできないですが、これはNote。復習と理解を深めていきます。>単方向リストの削除Note*




    まとめ

    お疲れ様でした!

    オブジェクト指向は、「オブジェクト名.属性名」「オブジェクト名.メソッド(引数)」で大方正解はできます。

    でも「何となく正解はできるけど…」で止まると、自分がプログラムを作る時/後輩さんに教える時に、必ず困ります。

    IT専門学校で授業してる私も困ってます。

    限られた時間枠の授業では「正解できる」程度で留めるしかないのですが。色んな学生さんがいるので、授業は平均点ちょい下にする必要もあるし。初学者に厳密解を教えても混乱させるだけです。

    しかし。「騙し騙し」社会人にさせて苦労させるのはカワイソウ。卒研までに/就職までには少なくとも一度はちゃんと向き合わねばなりません。

    よって補助教材として作りました。放課後の有志補講として活用して様子を見ています。

    少しでも合格の手助けになれば嬉しいです。

    でわ次回 >単方向リストの削除Note*でお会いしましょう!

    (・ω・▼)ノシ


    科目Bも全部作りました。

    60分で基礎を復習できます。
    >【2分×30節で読める基礎】擬似言語の教科書Note
    問題演習を通して見出すべきノウハウ。
    >【図解で流し見】擬似言語の解法11のNote
    基本課題12個+追加課題25個(現状)
    >FE科目BのSTEP4(目次)

    実力確認や模擬試験に。
    >令和07年科目Bの解説Note
    >令和06年科目Bの解説Note
    >令和05年科目Bの解説Note
    >サンプル科目B(1❶)の解説Note(擬似言語)
    >サンプル科目B(1❷)の解説Note(セキュリティ)
    >サンプル科目B(2)の解説Note

    またFE科目Bセキュリティは、SG科目Bが似ている(てか流用している)ので、問題演習として優秀です。>全Noteへのリンク(SG)

    良かったらご活用下さい。


     
     
    大学・専門学校の先生の解説Note。 学生時代にITパスポート試験・基本情報技術者試験・応用情報技術者試験を独学で高得点合格。情報処理安全確保支援士試験(セキスペ)・データベーススペシャリスト試験・ネットワークスペシャリスト試験・G検定なども取得。 2027年にPD-S受験予定。