LoginSignup
0
0

基本情報対策:小学生にもわかる?Classを使った単方向リストの作成。

Last updated at Posted at 2023-09-17

単方向リストは以前結構学んで、大分自信がついてきたので色々といてみたのですが、

サンプル問題のこちらの問題の動きがいまいちわからず、動きをしっかり追ってみました。

python での記述です。

問題:問題なので、こちらのコードは実行できません。

太文字が問題です。

class ListElement:
    def __init__(self, val):
        self.val = val
        self.next = None

# 大域変数の初期化
ListHead = None
curr = None
#current現在地
prev = None
#previosひとつ前

def append(qval):
    global ListHead  # 大域変数を参照するためのキーワード

    curr = List(qval)  # 新しいリストの要素を作成

    if  **<問題A:ListHeadが未定義 or 未定義でない>** :  
        ListHead = curr
    else:
        prev = ListHead
        while prev.next is not None:
            prev = prev.next
        prev.next = **<問題Bここに何が入るかな>**

回答:

問題A:未定義

問題B:curr

なんとなく解けるのではないでしょうか。

ただコードをの動きがいまいちわかりませんね。

疑問:

  1. if ListHead is None:は実行されるのか?

2.while prev.next is not None:はループに入るのか?

3.while prev.next is not None:は何回実行されるのか?

4.curr,prev,prev.nextの動き

そのため実際にコードを修正し、実行できるようにしてみました。

A,B,Cの順番でリストに入れます。

実行用コード:

class ListElement:
    def __init__(self, val):
        self.val = val
        self.next = None

# 大域変数の初期化
ListHead = None
curr = None
prev = None

def append(qval):
    global ListHead, curr, prev  # 大域変数を参照するためのキーワード

    curr = ListElement(qval)  # 新しいリストの要素を作成

    if ListHead is None:  # リストが空の場合
        ListHead = curr#ここで初めてリストの参照ができる。
    else:
        prev = ListHead
        while prev.next is not None:
            prev = prev.next
        prev.next = curr

# A, B, Cをリストに追加
append("A")
append("B")
append("C")

# 確認のためにリストの内容を表示
def print_list():
    global ListHead
    temp = ListHead
    while temp:
        print(temp.val)
        temp = temp.next

print_list()

実行できたのではないでしょうか。

動きを考えてみよう!

Aの参照を1とするまた、B:2,C:3とする!

1. if ListHead is None:は実行されるのか?

1**.Aを追加するとき**

  • 初めて**append関数が呼び出されると、currは新しいList**オブジェクト(A)の参照(1)を保持します。
  • **ListHeadはまだNoneなので、ListHeadcurr**の参照(1)が設定されます。
  • if ListHead is None:ここで実行される
  • **prev**はまだ使用されていません。

状態:

  • ListHead = 1(Aの参照)
  • curr = 1(Aの参照)
  • prev = 未使用

while prev.next is not None:のループには入るのか?

2.Bを追加するとき

  • **append関数が再度呼び出され、currは新しいList**オブジェクト(B)の参照(2)を保持します。
  • **ListHead**はAの参照(1)なので、elseブロックに進みます。
  • **prevListHead**の参照(1、Aの参照)が設定されます。
  • prev.nextNone(Aの次の要素はまだない)なので、whileループは実行されず、直接**prev.nextcurr**(Bの参照、2)が設定されます。
  • while prev.next is not None:には今回はループに入らない。

状態:

  • ListHead = 1(Aの参照)
  • curr = 2(Bの参照)
  • prev = 1(Aの参照)
  • prev.next = 2(Bの参照)

3.Cを追加するとき

  • **append関数が再度呼び出され、currは新しいList**オブジェクト(C)の参照(3)を保持します。
  • **ListHead**はAの参照(1)なので、elseブロックに進みます。
  • **prevListHead**の参照(1、Aの参照)が設定されます。
  • **prev.next**はBの参照(2)なので、whileループに入ります。
  • prevはBの参照(2)に更新され、そのprev.next(Bの次の要素)は**Noneです。ループは終了し、prev.nextcurr**(Cの参照、3)が設定されます。

状態:

  • ListHead = 1(Aの参照)
  • curr = 3(Cの参照)
  • prev = 2(Bの参照)
  • prev.next = 3(Cの参照)

最終的に、**ListHeadがAを指し、AのnextがBを指し、Bのnext**がCを指す形の単方向リンクドリストが完成します。

結果:

何か問題によって考え方が結構違うので、問題解きまくるしかないなあ。

prev.next.nextを最後に使う、どこに使うかわからないコードよりはだいぶましな問題だとは思う。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0