基本情報技術者試験2023サンプル問題 問3 単方向リスト pythonで書く

20221218基本情報技術者試験2023サンプル問題 問3python 単方向リスト

プログラム素人です。
python素人です。
間違いだらけです。

***********************************************************
問 3
次のプログラム中のaとbに入れる正しい答えの組合せを,解答群の中から選べ。

手続 append は,引数で与えられた文字を単方向リストに追加する手続である。単方向リストの各要素は,クラス ListElement を用いて表現する。クラス ListElement の説明を図に示す。ListElement 型の変数はクラス ListElement のインスタンスの参照を格納するものとする。大域変数 listHead は,単方向リストの先頭の要素の参照を格納する。リストが空のときは,listHead は未定義である。

メンバ変数    型    説明
val    文字型    リストに格納する文字。
next    ListElement    リストの次の文字を保持するインスタンスの参照。初期状態は未定義である。
コンストラクタ    説明
ListElement(文字型: qVal)    引数 qVal でメンバ変数 val を初期化する。
図 クラス ListElement の説明
〔プログラム〕

大域: ListElement: listHead ← 未定義の値
○append(文字型: qVal)
 ListElement: prev, curr
 curr ← ListElement(qVal)
 if (listHead が a)
   listHead ← curr
 else
   prev ← listHead
   while (prev.next が 未定義でない)
     prev ← prev.next
   endwhile
   prev.next ← b
 endif
解答群

a    b
ア    未定義    curr
イ    未定義    curr.next
ウ    未定義    listHead
エ    未定義でない    curr
オ    未定義でない    curr.next
カ    未定義でない    listHead
*****************************************************

上記の問題をpythonにしてみました。
素人なので分かってないところは、適当です。
コンストラクタの初期化とか。(「引数 qVal でメンバ変数 val を初期化する・・・ってpythonで簡単にできる?)

 

なお、アメリカの大学で奮闘中様の「連結リスト(Linked List)を大学生が解説してみた by python」を参考にしました。
大感謝。著作権等問題があれば削除します。

 

 

**************************

class ListElement:

    def __init__(self):
        self.ListHead = None

    class Node:
        def __init__(self, val):
            self.val = val
            self.next = None
            
    def append(self, Qval):
        curr = ListElement.Node(Qval)
        if self.ListHead == None:
                self.ListHead = curr
                return
        else:
            prev = self.ListHead
            while prev.next != None:
                prev = prev.next
            prev.next = curr
    #確認用        
    def printList(self): 
        temp = self.ListHead 
        while temp: 
            print(temp.val) 
            temp = temp.next            
            
            
tamesi = ListElement()
tamesi.append("谷")
tamesi.append("山")
tamesi.append("川")
#確認用
tamesi.printList()

========================================
解説的なメモ
この問題をきちんと解こうとするとオブジェクト指向を勉強しなくてはいけないのかも。
ただ、聞かれているのがif文についてなので、普通のVBAとかでも似た処理がある気がする。
(答えを見るとそう思うだけで、問題文はややこしい。)

この問題は、単方向リストのデータの追加方法について聞いている。
インデックス(通し番号)や配列ではなく、
谷 山 川
と単純に追加していく。

処理の流れ
まず、tamesi = ListElement()で、インスタンス化。
これでクラスの初期化がされる。
ListElement:

    def __init__(self):
        self.ListHead = None

リストの最初は何もなし。(Noneは大文字。)

次に、tamesi.append("谷")で、谷を渡す。
動くメソッドは、
    def append(self, Qval):
↑これ。Qvalに谷が入っている。

メソッド内の構文
        curr = ListElement.Node(Qval)
で、子クラス Nodeに飛ぶ。
    class Node:
        def __init__(self, val):
            self.val = val
            self.next = None

(名前の「Node」は何でもいい。)
Nodeで、谷を
Node.valに入れる
Node.Nextは何もなし。

(素人です。nextはコンピュータが認識して「次」のことだと分かっている。)
Node.Nextは、「谷」の次が「何もなし(None)」ということを覚えた。

ここで、
curr = ListElement.Node(Qval)
に戻り、Nodeでできた情報をcurrに入れる。

このcurrの情報で、リストを作成していく。
        if self.ListHead == None:
                self.ListHead = curr
                return
ListElementのListHeadに何もなければ(None)、curr(谷)を入れる。
returnでおしまい。
(ちなみにListHeadは本当にリストの先頭を指すので、このプログラムでは変わることはないです。)
これで、単方向リストの最初に「谷」が入った。

tamesi.append("山")の処理。
ここまでくれば同様の処理を回すだけ。
prevは、前の情報を指し、
        else:
            prev = self.ListHead
            while prev.next != None:
                prev = prev.next
ListHeadから順に回す。
谷の次はNoneなので、
            prev.next = curr
山を谷の次に入れる。
(ここでも、nextはコンピュータが認識して「次」のことだと分かっている。)
(また、prev = self.ListHeadとすることで、リスト全体をコンピュータが把握し、while文で回すことができる)


=============
思ったこと。
pythonは、命令文に省略が多く、なぞなぞっぽい。
paiza ioでやっているので、ステップ実行はできず、理解に手間がかかる。
オブジェクト指向は、クラスとインスタンスの関係だが、クラスの中に、
変数(クラス内で処理用の変数)←変数(インスタンスする関数からの引数)
という処理が多くなり、抽象度が高い。
ような気がします。VBAと比べて。