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

【オブジェクト指向】単方向リストの削除(FEBサンプル問題1問10, 基本情報技術者試験, 科目B, 午後, 擬似言語)擬似言語⑬Aの2

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

    下図のようにリストから要素を削除するdelNode()関数をトレースします。

    画像

    なおリストを作成するappend()関数は公開問題に出ており、前回のNoteで解説済みです。
    >【擬似言語⑬A1】単方向リストの作成/追加Note
    >【FEB】サンプル問題2問03のNote

    下図は、今回トレースするdelNode()関数の擬似言語。

    画像

    まずはdelNode(2)をトレースし(青)、実行されなかった部分の動作確認のためにdelNode(1)とdelNode(3)のトレースも追加学習します。

    公開問題に出た以上、しっかり深く復習したいですね。

    それでは始めましょう!


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

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


    今回の全体像

    delNode(2)関数で、リストの2番目要素を削除をします。

    下記がメイン処理。大域宣言~append関数3回で、リスト(A→K→T)を作ります。トレースは前回のNote。>【擬似言語⑬A1】単方向リストの作成/追加Note

    画像

    delNode関数は、リスト内の引数番目の要素を削除します。例えばdelNode(2)なら2番目の要素(K)が削除され、元(A→K→T)が(A→T)になります。

    下図が今回の全擬似言語。

    〔プログラム〕
      大域: ListElement: listHead  // リストの先頭要素が格納されている
      append("A")
      append("K")
      append("T")
      delNode(2)
    
      ○delNode(整数型: pos)  /* posは,リストの要素数以下の正の整数 */
        ListElement: prev
        整数型: i
        if (pos が 1 と等しい)
          listHead ← listHead.next
        else
          prev ← listHead
          /* posが2と等しいときは繰返し処理を実行しない */
          for (i を 2 から pos - 1 まで 1 ずつ増やす)
            prev ← prev.next
          endfor
          prev.next ← prev.next.next
        endif




    事前準備

    append関数でリストを作ります。前回のNoteでトレース済みなので結論のみ。>【擬似言語⑬A1】単方向リストの作成/追加Note

    listHeadにリスト先頭のアドレス値(メモリでの保存場所)が記録され、.nextで紐づけられリストが構築されます。

    画像

    青文字の擬似言語を実行したら、下青図の状況になります。残りの黒字delNode(2)のトレースを次節からします。




    delNode(2)のトレース

    色表現は 前回のNoteと同じ。>【擬似言語⑬A1】単方向リストの作成/追加Note

    擬似言語1行1行で変化した部分に色を付け(青, 緑, 水色)。注目/注意すべき点も(緑, 赤)。最初の1~2行が擬似言語、3行目以降に、変数/メモリ(データ)の作成状況。アドレス値を記録したポインタ変数は値と矢印で表現。

    1行目は、prevを作るだけ。prevはListElement型データのアドレスを記録するポインタ変数。まだどこも指していません(未定義)。

    画像

    上図の下。2行目のif文の判定。delNode(2)で引数pos=2、判定はFalse。次からelse文の実行をトレースします。

    下図。else文の1行目。prevにアドレスが代入され、prevは”A”があるデータを指すようになりました。つまりリストの1番目を指す。

    画像

    else文2行目はfor文。

    delNode(2)よりpos=2なので、for文は「iを2から1まで1ずつ増やす」。for文内は実行されません。

    画像


    for文を実行せずスルーして、for文直後/else文最後の1行。

    今回最難関「prev.next←prev.next.next」を解釈します。

    「←」で上書きされるので、❶❷❸と順を追って理解して下さいね。一気にやろうとすると混乱するかも。

    画像

    ❶prev.nextは、prevの属性値nextを指します。上図上よりprevはアドレス100のオブジェクトを指し、属性値next=300。
    ただし、今回のクラス定義では「.next」もポインタ変数。値(アドレス)であると同時に、ListElement型データも指しています。
    つまり、prev.nextは「300」であると同時に、アドレス300にある「ListElement型データ=Kのやつ」でもあります。

    ❷「prev.next.next」は「次の次のモノ」を意味します。prev.nextで300/"K"があるオブジェクト。prev.next.nextは200/"T"があるオブジェクトを指します。

    ❸「prev.next←prev.next.next」で、「"A"オブジェクトのnext」に「"T"オブジェクト」のアドレスで上書きしてます。AからKへの繋がりが、AからTへの繋がりに変更されます。

    ❶❷❸を経て、delNode関数は終了。


    delNode()関数が終了したら、局所なprevは喪失します。大域なlistHeadは残ります。

    画像

    listHeadからA→Tと辿れるようになりました。Kの200からも紐づいてますが、K(アドレス300)に行くことはないので問題ありません。

    なお。追うのは沼ですが。アドレス300も200もappend関数内で作成したので喪失しそうですが、プログラム言語がうまいことします。まだ必要な200を残し、不要になった300を消す(他データで上書き)など。




    全体フローと見たい処理

    delNode(2)で辿ったルートを青線で描きました。

    画像

    実行されなかったのは、緑と橙。
    発動条件を考えます。
    緑:pos=1で発動。delNode(1)なら実行される。
    橙:for文はdelNode(3)なら1回実行される。

    次節で見ます。

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